yql_dispatch.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #pragma once
  2. #include "yql_setting.h"
  3. #include <yql/essentials/core/yql_expr_type_annotation.h>
  4. #include <library/cpp/string_utils/parse_size/parse_size.h>
  5. #include <util/string/cast.h>
  6. #include <util/string/join.h>
  7. #include <util/string/builder.h>
  8. #include <util/datetime/base.h>
  9. #include <util/generic/ptr.h>
  10. #include <util/generic/string.h>
  11. #include <util/generic/strbuf.h>
  12. #include <util/generic/hash.h>
  13. #include <util/generic/hash_set.h>
  14. #include <util/generic/yexception.h>
  15. #include <util/generic/vector.h>
  16. #include <util/generic/guid.h>
  17. #include <util/generic/maybe.h>
  18. #include <util/generic/algorithm.h>
  19. namespace NYql {
  20. namespace NPrivate {
  21. template <typename TType>
  22. using TParser = std::function<TType(const TString&)>;
  23. template <typename TType>
  24. TParser<TType> GetDefaultParser() {
  25. return [] (const TString&) -> TType { throw yexception() << "Unsupported parser"; };
  26. }
  27. template <>
  28. TParser<TString> GetDefaultParser<TString>();
  29. template<>
  30. TParser<bool> GetDefaultParser<bool>();
  31. template <>
  32. TParser<TGUID> GetDefaultParser<TGUID>();
  33. template<>
  34. TParser<NSize::TSize> GetDefaultParser<NSize::TSize>();
  35. template<>
  36. TParser<TInstant> GetDefaultParser<TInstant>();
  37. #define YQL_PRIMITIVE_SETTING_PARSER_TYPES(XX) \
  38. XX(ui8) \
  39. XX(ui16) \
  40. XX(ui32) \
  41. XX(ui64) \
  42. XX(i8) \
  43. XX(i16) \
  44. XX(i32) \
  45. XX(i64) \
  46. XX(float) \
  47. XX(double) \
  48. XX(TDuration)
  49. #define YQL_CONTAINER_SETTING_PARSER_TYPES(XX) \
  50. XX(TVector<TString>) \
  51. XX(TSet<TString>) \
  52. XX(THashSet<TString>)
  53. #define YQL_DECLARE_SETTING_PARSER(type) \
  54. template<> \
  55. TParser<type> GetDefaultParser<type>();
  56. YQL_PRIMITIVE_SETTING_PARSER_TYPES(YQL_DECLARE_SETTING_PARSER)
  57. YQL_CONTAINER_SETTING_PARSER_TYPES(YQL_DECLARE_SETTING_PARSER)
  58. template<typename TType>
  59. TMaybe<TType> GetValue(const NCommon::TConfSetting<TType, true>& setting, const TString& cluster) {
  60. return setting.Get(cluster);
  61. }
  62. template<typename TType>
  63. TMaybe<TType> GetValue(const NCommon::TConfSetting<TType, false>& setting, const TString& cluster) {
  64. Y_UNUSED(cluster);
  65. return setting.Get();
  66. }
  67. }
  68. namespace NCommon {
  69. class TSettingDispatcher: public TThrRefBase {
  70. public:
  71. using TPtr = TIntrusivePtr<TSettingDispatcher>;
  72. // Returns true if can continue
  73. using TErrorCallback = std::function<bool(const TString& message, bool isError)>;
  74. enum class EStage {
  75. CONFIG,
  76. STATIC,
  77. RUNTIME,
  78. };
  79. class TSettingHandler: public TThrRefBase {
  80. public:
  81. using TPtr = TIntrusivePtr<TSettingHandler>;
  82. TSettingHandler(const TString& name)
  83. : Name_(name)
  84. {
  85. }
  86. const TString& GetDisplayName() const {
  87. return Name_ ;
  88. }
  89. virtual bool Handle(const TString& cluster, const TMaybe<TString>& value, bool validateOnly, const TErrorCallback& errorCallback) = 0;
  90. virtual void FreezeDefault() = 0;
  91. virtual void Restore(const TString& cluster) = 0;
  92. virtual bool IsRuntime() const = 0;
  93. protected:
  94. TString Name_;
  95. };
  96. template <typename TType, bool RUNTIME>
  97. class TSettingHandlerImpl: public TSettingHandler {
  98. public:
  99. using TValueCallback = std::function<void(const TString&, TType)>;
  100. private:
  101. friend class TSettingDispatcher;
  102. TSettingHandlerImpl(const TString& name, TConfSetting<TType, RUNTIME>& setting)
  103. : TSettingHandler(name)
  104. , Setting_(setting)
  105. , Parser_(::NYql::NPrivate::GetDefaultParser<TType>())
  106. , ValueSetter_([this](const TString& cluster, TType value) {
  107. Setting_[cluster] = value;
  108. })
  109. {
  110. }
  111. bool Handle(const TString& cluster, const TMaybe<TString>& value, bool validateOnly, const TErrorCallback& errorCallback) override {
  112. if (value) {
  113. try {
  114. TType v = Parser_(*value);
  115. for (auto& validate: Validators_) {
  116. validate(cluster, v);
  117. }
  118. if (!validateOnly) {
  119. ValueSetter_(cluster, v);
  120. if (Warning_) {
  121. return errorCallback(Warning_, false);
  122. }
  123. }
  124. } catch (...) {
  125. return errorCallback(TStringBuilder() << "Bad " << Name_.Quote() << " setting for " << cluster.Quote() << " cluster: " << CurrentExceptionMessage(), true);
  126. }
  127. } else if (!validateOnly) {
  128. try {
  129. Restore(cluster);
  130. } catch (...) {
  131. return errorCallback(CurrentExceptionMessage(), true);
  132. }
  133. }
  134. return true;
  135. }
  136. void FreezeDefault() override {
  137. Defaul_ = Setting_;
  138. }
  139. void Restore(const TString& cluster) override {
  140. if (!Defaul_) {
  141. ythrow yexception() << "Cannot restore " << Name_.Quote() << " setting without freeze";
  142. }
  143. if (ALL_CLUSTERS == cluster) {
  144. Setting_ = Defaul_.GetRef();
  145. } else {
  146. if (auto value = NPrivate::GetValue(Defaul_.GetRef(), cluster)) {
  147. Setting_[cluster] = *value;
  148. } else {
  149. Setting_.Clear();
  150. }
  151. }
  152. }
  153. public:
  154. bool IsRuntime() const override {
  155. return Setting_.IsRuntime();
  156. }
  157. TSettingHandlerImpl& Lower(TType lower) {
  158. Validators_.push_back([lower](const TString&, TType value) {
  159. if (value < lower) {
  160. throw yexception() << "Value " << value << " is less than " << lower << " allowed lower bound";
  161. }
  162. });
  163. return *this;
  164. }
  165. TSettingHandlerImpl& Upper(TType upper) {
  166. Validators_.push_back([upper](const TString&, TType value) {
  167. if (value > upper) {
  168. throw yexception() << "Value " << value << " is greater than " << upper << " allowed upper bound";
  169. }
  170. });
  171. return *this;
  172. }
  173. template <class TContainer>
  174. TSettingHandlerImpl& Enum(const TContainer& container) {
  175. THashSet<TType> allowed(container.cbegin(), container.cend());
  176. Validators_.push_back([allowed = std::move(allowed)](const TString&, TType value) {
  177. if (!allowed.has(value)) {
  178. throw yexception() << "Value " << value << " is not in set of allowed values: " << JoinSeq(TStringBuf(","), allowed);
  179. }
  180. });
  181. return *this;
  182. }
  183. TSettingHandlerImpl& Enum(std::initializer_list<TType> list) {
  184. THashSet<TType> allowed(list);
  185. Validators_.push_back([allowed = std::move(allowed)](const TString&, TType value) {
  186. if (!allowed.contains(value)) {
  187. throw yexception() << "Value " << value << " is not in set of allowed values: " << JoinSeq(TStringBuf(","), allowed);
  188. }
  189. });
  190. return *this;
  191. }
  192. TSettingHandlerImpl& NonEmpty() {
  193. Validators_.push_back([](const TString&, TType value) {
  194. if (value.empty()) {
  195. throw yexception() << "Value is empty";
  196. }
  197. });
  198. return *this;
  199. }
  200. TSettingHandlerImpl& GlobalOnly() {
  201. Validators_.push_back([] (const TString& cluster, TType) {
  202. if (cluster != NCommon::ALL_CLUSTERS) {
  203. throw yexception() << "Option cannot be used with specific cluster";
  204. }
  205. });
  206. return *this;
  207. }
  208. TSettingHandlerImpl& Validator(TValueCallback&& validator) {
  209. Validators_.push_back(std::move(validator));
  210. return *this;
  211. }
  212. TSettingHandlerImpl& Validator(const TValueCallback& validator) {
  213. Validators_.push_back(validator);
  214. return *this;
  215. }
  216. TSettingHandlerImpl& Parser(::NYql::NPrivate::TParser<TType>&& parser) {
  217. Parser_ = std::move(parser);
  218. return *this;
  219. }
  220. TSettingHandlerImpl& Parser(const ::NYql::NPrivate::TParser<TType>& parser) {
  221. Parser_ = parser;
  222. return *this;
  223. }
  224. TSettingHandlerImpl& ValueSetter(TValueCallback&& hook) {
  225. ValueSetter_ = std::move(hook);
  226. return *this;
  227. }
  228. TSettingHandlerImpl& ValueSetter(const TValueCallback& hook) {
  229. ValueSetter_ = hook;
  230. return *this;
  231. }
  232. TSettingHandlerImpl& ValueSetterWithRestore(TValueCallback&& hook) {
  233. ValueSetter_ = [this, hook = std::move(hook)] (const TString& cluster, TType value) {
  234. if (Defaul_) {
  235. Restore(cluster);
  236. }
  237. hook(cluster, value);
  238. };
  239. return *this;
  240. }
  241. TSettingHandlerImpl& ValueSetterWithRestore(const TValueCallback& hook) {
  242. ValueSetter_ = [this, hook] (const TString& cluster, TType value) {
  243. if (Defaul_) {
  244. Restore(cluster);
  245. }
  246. hook(cluster, value);
  247. };
  248. return *this;
  249. }
  250. TSettingHandlerImpl& Warning(const TString& message) {
  251. Warning_ = message;
  252. return *this;
  253. }
  254. TSettingHandlerImpl& Deprecated() {
  255. Warning_ = TStringBuilder() << "Pragma \"" << Name_ << "\" is deprecated and has no effect";
  256. return *this;
  257. }
  258. private:
  259. TConfSetting<TType, RUNTIME>& Setting_;
  260. TMaybe<TConfSetting<TType, RUNTIME>> Defaul_;
  261. ::NYql::NPrivate::TParser<TType> Parser_;
  262. TValueCallback ValueSetter_;
  263. TVector<TValueCallback> Validators_;
  264. TString Warning_;
  265. };
  266. TSettingDispatcher() = default;
  267. TSettingDispatcher(const TSettingDispatcher&) = delete;
  268. template <class TContainer>
  269. TSettingDispatcher(const TContainer& validClusters)
  270. : ValidClusters(validClusters.begin(), validClusters.end())
  271. {
  272. }
  273. template <class TContainer>
  274. void SetValidClusters(const TContainer& validClusters) {
  275. ValidClusters.clear();
  276. ValidClusters.insert(validClusters.begin(), validClusters.end());
  277. }
  278. void AddValidCluster(const TString& cluster) {
  279. ValidClusters.insert(cluster);
  280. }
  281. template <typename TType, bool RUNTIME>
  282. TSettingHandlerImpl<TType, RUNTIME>& AddSetting(const TString& name, TConfSetting<TType, RUNTIME>& setting) {
  283. TIntrusivePtr<TSettingHandlerImpl<TType, RUNTIME>> handler = new TSettingHandlerImpl<TType, RUNTIME>(name, setting);
  284. if (!Handlers.insert({NormalizeName(name), handler}).second) {
  285. ythrow yexception() << "Duplicate configuration setting name " << name.Quote();
  286. }
  287. return *handler;
  288. }
  289. bool IsRuntime(const TString& name);
  290. bool Dispatch(const TString& cluster, const TString& name, const TMaybe<TString>& value, EStage stage, const TErrorCallback& errorCallback);
  291. template <class TContainer, typename TFilter>
  292. void Dispatch(const TString& cluster, const TContainer& clusterValues, const TFilter& filter) {
  293. auto errorCallback = GetDefaultErrorCallback();
  294. for (auto& v: clusterValues) {
  295. if (filter(v)) {
  296. Dispatch(cluster, v.GetName(), v.GetValue(), EStage::CONFIG, errorCallback);
  297. }
  298. }
  299. }
  300. template <class TContainer>
  301. void Dispatch(const TString& cluster, const TContainer& clusterValues) {
  302. auto errorCallback = GetDefaultErrorCallback();
  303. for (auto& v: clusterValues) {
  304. Dispatch(cluster, v.GetName(), v.GetValue(), EStage::CONFIG, errorCallback);
  305. }
  306. }
  307. template <class TContainer, typename TFilter>
  308. void Dispatch(const TContainer& globalValues, const TFilter& filter) {
  309. Dispatch(ALL_CLUSTERS, globalValues, filter);
  310. }
  311. template <class TContainer>
  312. void Dispatch(const TContainer& globalValues) {
  313. Dispatch(ALL_CLUSTERS, globalValues);
  314. }
  315. void FreezeDefaults();
  316. void Restore();
  317. static TErrorCallback GetDefaultErrorCallback();
  318. static TErrorCallback GetErrorCallback(TPositionHandle pos, TExprContext& ctx);
  319. protected:
  320. THashSet<TString> ValidClusters;
  321. THashMap<TString, TSettingHandler::TPtr> Handlers;
  322. };
  323. } // namespace NCommon
  324. } // namespace NYql
  325. #define REGISTER_SETTING(dispatcher, setting) \
  326. (dispatcher).AddSetting(#setting, setting)