diff options
| author | arkady-e1ppa <[email protected]> | 2024-11-29 22:02:21 +0300 |
|---|---|---|
| committer | arkady-e1ppa <[email protected]> | 2024-11-29 22:12:26 +0300 |
| commit | b21317884da9622ac16bbad26627ae014d72d6a7 (patch) | |
| tree | 1af2253192c15fba295fdde1d23d6c7fc6792401 | |
| parent | 0924e1c53b7aec2c5efefe89499154b0a7e902f7 (diff) | |
YT-21233: Introduce ToAttributeValue cpo which removes dependency of TErrorAttribute from yt/core
Plan:
1) Remove `IAttributedDictionary` type from the public API. \+
2) Remove `Set` method from public API in favor of `operator<<=`. \+
3) Adopt `ConvertTo<T>` (or other name) CPO with proper extension into `NYT::NYson::ConvertTo` from `yt/core`.
4) Use CPO from (3) to eliminate direct dependency on `yt/core` of `Get/Find` methods from attributes API.
5) Adopt `ConvertToYsonString` (or other name) CPO with proper extension into `yt/core` customisations.
6) Use CPO from (5) to eliminate direct dependency on `yt/core` of `TErrorAttribute` ctor.
7) Swap attributes implementation to the one which doesn’t use `IAttributeDictionary`.
8) At this point `stripped_error*` can be moved to library/cpp/yt and so can recursively dependant on THROW macro methods `Get/Find/…`.
9) Adjust CPO’s to work with `std::string` instead of `TYsonString` assuming text format to be used (maybe `TString` for now).
10) Remove dep of `library/cpp/yt/error` on `yson` entirely.
This pr addresses 5-6 steps of plan. Below is a brief explanation of design decisions. We also expressed everything related to key-value code in terms of aliases of `TErrorAttribute` so that later we could make a relatively simple switch to `std::string`. We expect to do steps 7-8 in the next pull request as everything should be ready
commit_hash:de9feca2bd24d823b33d904ef0fa5f4856f9b020
| -rw-r--r-- | library/cpp/yt/error/convert_to_cpo.h | 4 | ||||
| -rw-r--r-- | library/cpp/yt/error/error_attribute.h | 57 | ||||
| -rw-r--r-- | library/cpp/yt/error/error_attributes-inl.h | 18 | ||||
| -rw-r--r-- | library/cpp/yt/error/error_attributes.cpp | 2 | ||||
| -rw-r--r-- | library/cpp/yt/error/error_attributes.h | 35 | ||||
| -rw-r--r-- | library/cpp/yt/error/mergeable_dictionary.h | 6 | ||||
| -rw-r--r-- | library/cpp/yt/error/public.h | 2 | ||||
| -rw-r--r-- | yt/yt/core/misc/error-inl.h | 24 | ||||
| -rw-r--r-- | yt/yt/core/misc/error.h | 4 | ||||
| -rw-r--r-- | yt/yt/core/misc/stripped_error.cpp | 10 | ||||
| -rw-r--r-- | yt/yt/core/misc/stripped_error.h | 19 | ||||
| -rw-r--r-- | yt/yt/core/ytree/convert-inl.h | 32 |
12 files changed, 143 insertions, 70 deletions
diff --git a/library/cpp/yt/error/convert_to_cpo.h b/library/cpp/yt/error/convert_to_cpo.h index 55f608c3b60..dcfc8b0677d 100644 --- a/library/cpp/yt/error/convert_to_cpo.h +++ b/library/cpp/yt/error/convert_to_cpo.h @@ -2,8 +2,6 @@ #include <library/cpp/yt/misc/tag_invoke_cpo.h> -#include <util/generic/strbuf.h> - namespace NYT { //////////////////////////////////////////////////////////////////////////////// @@ -34,7 +32,7 @@ inline constexpr NConvertToImpl::TFn<T> ConvertTo = {}; //////////////////////////////////////////////////////////////////////////////// template <class TTo, class TFrom> -concept CConvertToWorks = requires (const TFrom& from) { +concept CConvertsTo = requires (const TFrom& from) { { NYT::ConvertTo<TTo>(from) } -> std::same_as<TTo>; }; diff --git a/library/cpp/yt/error/error_attribute.h b/library/cpp/yt/error/error_attribute.h new file mode 100644 index 00000000000..dec4a4dd9b3 --- /dev/null +++ b/library/cpp/yt/error/error_attribute.h @@ -0,0 +1,57 @@ +#pragma once + +#include <library/cpp/yt/misc/tag_invoke_cpo.h> + +// TODO(arkady-e1ppa): Eliminate. +#include <library/cpp/yt/yson_string/string.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +namespace NToAttributeValueImpl { + +struct TFn + : public TTagInvokeCpoBase<TFn> +{ }; + +} // namespace NToAttributeValueImpl + +//////////////////////////////////////////////////////////////////////////////// + +inline constexpr NToAttributeValueImpl::TFn ToAttributeValue = {}; + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +concept CConvertibleToAttributeValue = CTagInvocableS< + TTagInvokeTag<ToAttributeValue>, + NYson::TYsonString(const T&)>; + +//////////////////////////////////////////////////////////////////////////////// + +struct TErrorAttribute +{ + // NB(arkady-e1ppa): Switch to std::string is quite possible + // however it requires patching IAttributeDictionary or + // switching it to the std::string first for interop reasons. + // Do that later. + using TKey = TString; + // TODO(arkady-e1ppa): Use ConvertToYsonString(value, Format::Text) + // here for complex values. Write manual implementations as ToString + // for primitive types (e.g. integral types, guid, string, time). + using TValue = NYson::TYsonString; + + template <CConvertibleToAttributeValue T> + TErrorAttribute(const TKey& key, const T& value) + : Key(key) + , Value(NYT::ToAttributeValue(value)) + { } + + TKey Key; + TValue Value; +}; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/library/cpp/yt/error/error_attributes-inl.h b/library/cpp/yt/error/error_attributes-inl.h index 8ffbf3e0a39..6574665865b 100644 --- a/library/cpp/yt/error/error_attributes-inl.h +++ b/library/cpp/yt/error/error_attributes-inl.h @@ -9,7 +9,7 @@ namespace NYT { //////////////////////////////////////////////////////////////////////////////// template <class T> - requires CConvertToWorks<T, TErrorAttributes::TValue> + requires CConvertsTo<T, TErrorAttributes::TValue> T TErrorAttributes::Get(TStringBuf key) const { auto yson = GetYson(key); @@ -21,7 +21,7 @@ T TErrorAttributes::Get(TStringBuf key) const } template <class T> - requires CConvertToWorks<T, TErrorAttributes::TValue> + requires CConvertsTo<T, TErrorAttributes::TValue> typename TOptionalTraits<T>::TOptional TErrorAttributes::Find(TStringBuf key) const { auto yson = FindYson(key); @@ -36,8 +36,8 @@ typename TOptionalTraits<T>::TOptional TErrorAttributes::Find(TStringBuf key) co } template <class T> - requires CConvertToWorks<T, TErrorAttributes::TValue> -T TErrorAttributes::GetAndRemove(const TString& key) + requires CConvertsTo<T, TErrorAttributes::TValue> +T TErrorAttributes::GetAndRemove(const TKey& key) { auto result = Get<T>(key); Remove(key); @@ -45,15 +45,15 @@ T TErrorAttributes::GetAndRemove(const TString& key) } template <class T> - requires CConvertToWorks<T, TErrorAttributes::TValue> + requires CConvertsTo<T, TErrorAttributes::TValue> T TErrorAttributes::Get(TStringBuf key, const T& defaultValue) const { return Find<T>(key).value_or(defaultValue); } template <class T> - requires CConvertToWorks<T, TErrorAttributes::TValue> -T TErrorAttributes::GetAndRemove(const TString& key, const T& defaultValue) + requires CConvertsTo<T, TErrorAttributes::TValue> +T TErrorAttributes::GetAndRemove(const TKey& key, const T& defaultValue) { auto result = Find<T>(key); if (result) { @@ -65,8 +65,8 @@ T TErrorAttributes::GetAndRemove(const TString& key, const T& defaultValue) } template <class T> - requires CConvertToWorks<T, TErrorAttributes::TValue> -typename TOptionalTraits<T>::TOptional TErrorAttributes::FindAndRemove(const TString& key) + requires CConvertsTo<T, TErrorAttributes::TValue> +typename TOptionalTraits<T>::TOptional TErrorAttributes::FindAndRemove(const TKey& key) { auto result = Find<T>(key); if (result) { diff --git a/library/cpp/yt/error/error_attributes.cpp b/library/cpp/yt/error/error_attributes.cpp index 2c1b5423146..09aa48eebb9 100644 --- a/library/cpp/yt/error/error_attributes.cpp +++ b/library/cpp/yt/error/error_attributes.cpp @@ -15,7 +15,7 @@ void TErrorAttributes::Clear() } } -NYson::TYsonString TErrorAttributes::GetYsonAndRemove(const TString& key) +TErrorAttributes::TValue TErrorAttributes::GetYsonAndRemove(const TKey& key) { auto result = GetYson(key); Remove(key); diff --git a/library/cpp/yt/error/error_attributes.h b/library/cpp/yt/error/error_attributes.h index 7c2f4a54078..80dd80de484 100644 --- a/library/cpp/yt/error/error_attributes.h +++ b/library/cpp/yt/error/error_attributes.h @@ -1,6 +1,7 @@ #pragma once #include "convert_to_cpo.h" +#include "error_attribute.h" #include "mergeable_dictionary.h" #include <library/cpp/yt/misc/optional.h> @@ -20,34 +21,34 @@ namespace NYT { class TErrorAttributes { public: - using TKey = TString; - using TValue = NYson::TYsonString; + using TKey = TErrorAttribute::TKey; + using TValue = TErrorAttribute::TValue; using TKeyValuePair = std::pair<TKey, TValue>; //! Returns the list of all keys in the dictionary. - std::vector<TString> ListKeys() const; + std::vector<TKey> ListKeys() const; //! Returns the list of all key-value pairs in the dictionary. std::vector<TKeyValuePair> ListPairs() const; //! Returns the value of the attribute (null indicates that the attribute is not found). - NYson::TYsonString FindYson(TStringBuf key) const; + TValue FindYson(TStringBuf key) const; //! Sets the value of the attribute. - void SetYson(const TString& key, const NYson::TYsonString& value); + void SetYson(const TKey& key, const TValue& value); //! Removes the attribute. //! Returns |true| if the attribute was removed or |false| if there is no attribute with this key. - bool Remove(const TString& key); + bool Remove(const TKey& key); //! Removes all attributes. void Clear(); //! Returns the value of the attribute (throws an exception if the attribute is not found). - NYson::TYsonString GetYson(TStringBuf key) const; + TValue GetYson(TStringBuf key) const; //! Same as #GetYson but removes the value. - NYson::TYsonString GetYsonAndRemove(const TString& key); + TValue GetYsonAndRemove(const TKey& key); //! Returns |true| iff the given key is present. bool Contains(TStringBuf key) const; @@ -58,35 +59,35 @@ public: //! Finds the attribute and deserializes its value. //! Throws if no such value is found. template <class T> - requires CConvertToWorks<T, TValue> + requires CConvertsTo<T, TValue> T Get(TStringBuf key) const; //! Same as #Get but removes the value. template <class T> - requires CConvertToWorks<T, TValue> - T GetAndRemove(const TString& key); + requires CConvertsTo<T, TValue> + T GetAndRemove(const TKey& key); //! Finds the attribute and deserializes its value. //! Uses default value if no such attribute is found. template <class T> - requires CConvertToWorks<T, TValue> + requires CConvertsTo<T, TValue> T Get(TStringBuf key, const T& defaultValue) const; //! Same as #Get but removes the value if it exists. template <class T> - requires CConvertToWorks<T, TValue> - T GetAndRemove(const TString& key, const T& defaultValue); + requires CConvertsTo<T, TValue> + T GetAndRemove(const TKey& key, const T& defaultValue); //! Finds the attribute and deserializes its value. //! Returns null if no such attribute is found. template <class T> - requires CConvertToWorks<T, TValue> + requires CConvertsTo<T, TValue> typename TOptionalTraits<T>::TOptional Find(TStringBuf key) const; //! Same as #Find but removes the value if it exists. template <class T> - requires CConvertToWorks<T, TValue> - typename TOptionalTraits<T>::TOptional FindAndRemove(const TString& key); + requires CConvertsTo<T, TValue> + typename TOptionalTraits<T>::TOptional FindAndRemove(const TKey& key); template <CMergeableDictionary TDictionary> void MergeFrom(const TDictionary& dict); diff --git a/library/cpp/yt/error/mergeable_dictionary.h b/library/cpp/yt/error/mergeable_dictionary.h index 90597059e40..361694d8416 100644 --- a/library/cpp/yt/error/mergeable_dictionary.h +++ b/library/cpp/yt/error/mergeable_dictionary.h @@ -1,6 +1,7 @@ #pragma once #include "public.h" +#include "error_attribute.h" #include <ranges> @@ -23,6 +24,7 @@ namespace NDetail { template <class T> struct TMergeableDictionaryImpl { + // TL;DR: MakeIterableView returns something like std::span<std::pair<TKey, TValue>>. using TView = std::invoke_result_t<decltype(&TMergeDictionariesTraits<T>::MakeIterableView), const T&>; using TIterator = std::ranges::iterator_t<TView>; using TValue = typename std::iterator_traits<TIterator>::value_type; @@ -33,10 +35,10 @@ struct TMergeableDictionaryImpl static constexpr bool CorrectTupleElements = requires { typename std::tuple_element<0, TValue>::type; - std::same_as<typename std::tuple_element<0, TValue>::type, TString>; + std::same_as<typename std::tuple_element<0, TValue>::type, TErrorAttribute::TKey>; typename std::tuple_element<1, TValue>::type; - std::same_as<typename std::tuple_element<1, TValue>::type, NYson::TYsonString>; + std::same_as<typename std::tuple_element<1, TValue>::type, TErrorAttribute::TValue>; }; }; diff --git a/library/cpp/yt/error/public.h b/library/cpp/yt/error/public.h index 63b95497c7b..04201128aa3 100644 --- a/library/cpp/yt/error/public.h +++ b/library/cpp/yt/error/public.h @@ -9,6 +9,8 @@ namespace NYT { template <class T> class TErrorOr; + +struct TErrorAttribute; class TErrorAttributes; struct TOriginAttributes; diff --git a/yt/yt/core/misc/error-inl.h b/yt/yt/core/misc/error-inl.h new file mode 100644 index 00000000000..3185de11b2e --- /dev/null +++ b/yt/yt/core/misc/error-inl.h @@ -0,0 +1,24 @@ +#ifndef ERROR_INL_H_ +#error "Direct inclusion of this file is not allowed, include error.h" +// For the sake of sane code completion. +#include "error.h" +#endif + +namespace NYT::NToAttributeValueImpl { + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +NYson::TYsonString TagInvoke(TTagInvokeTag<ToAttributeValue>, const T& value) +{ + return NYson::ConvertToYsonString(value); +} + +inline NYson::TYsonString TagInvoke(TTagInvokeTag<ToAttributeValue>, const NYson::TYsonString& value) +{ + return value; +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NToAttributeValueImpl diff --git a/yt/yt/core/misc/error.h b/yt/yt/core/misc/error.h index f3c773da338..8399b49301d 100644 --- a/yt/yt/core/misc/error.h +++ b/yt/yt/core/misc/error.h @@ -91,3 +91,7 @@ struct TSerializerTraits< //////////////////////////////////////////////////////////////////////////////// } // namespace NYT + +#define ERROR_INL_H_ +#include "error-inl.h" +#undef ERROR_INL_H_ diff --git a/yt/yt/core/misc/stripped_error.cpp b/yt/yt/core/misc/stripped_error.cpp index e43a61953f1..5be93260f93 100644 --- a/yt/yt/core/misc/stripped_error.cpp +++ b/yt/yt/core/misc/stripped_error.cpp @@ -205,7 +205,7 @@ private: // which has minimal API of original dict with backend being the // actual original dict. Once API-related issues are fixed we are // free to implement a backend which doesn't depend on original dict. -std::vector<TString> TErrorAttributes::ListKeys() const +std::vector<TErrorAttributes::TKey> TErrorAttributes::ListKeys() const { auto* attributes = static_cast<IAttributeDictionary*>(Attributes_); if (!attributes) { @@ -223,7 +223,7 @@ std::vector<TErrorAttributes::TKeyValuePair> TErrorAttributes::ListPairs() const return attributes->ListPairs(); } -NYson::TYsonString TErrorAttributes::FindYson(TStringBuf key) const +TErrorAttributes::TValue TErrorAttributes::FindYson(TStringBuf key) const { auto* attributes = static_cast<IAttributeDictionary*>(Attributes_); if (!attributes) { @@ -232,14 +232,14 @@ NYson::TYsonString TErrorAttributes::FindYson(TStringBuf key) const return attributes->FindYson(key); } -void TErrorAttributes::SetYson(const TString& key, const NYson::TYsonString& value) +void TErrorAttributes::SetYson(const TKey& key, const TValue& value) { auto* attributes = static_cast<IAttributeDictionary*>(Attributes_); YT_VERIFY(attributes); return attributes->SetYson(key, value); } -bool TErrorAttributes::Remove(const TString& key) +bool TErrorAttributes::Remove(const TKey& key) { auto* attributes = static_cast<IAttributeDictionary*>(Attributes_); if (!attributes) { @@ -248,7 +248,7 @@ bool TErrorAttributes::Remove(const TString& key) return attributes->Remove(key); } -NYson::TYsonString TErrorAttributes::GetYson(TStringBuf key) const +TErrorAttributes::TValue TErrorAttributes::GetYson(TStringBuf key) const { auto result = FindYson(key); if (!result) { diff --git a/yt/yt/core/misc/stripped_error.h b/yt/yt/core/misc/stripped_error.h index ad985394b8f..6dd7b4b87ee 100644 --- a/yt/yt/core/misc/stripped_error.h +++ b/yt/yt/core/misc/stripped_error.h @@ -60,25 +60,6 @@ void FormatValue(TStringBuilderBase* builder, TErrorCode code, TStringBuf spec); //////////////////////////////////////////////////////////////////////////////// -struct TErrorAttribute -{ - template <class T> - TErrorAttribute(const TString& key, const T& value) - : Key(key) - , Value(NYson::ConvertToYsonString(value)) - { } - - TErrorAttribute(const TString& key, const NYson::TYsonString& value) - : Key(key) - , Value(value) - { } - - TString Key; - NYson::TYsonString Value; -}; - -//////////////////////////////////////////////////////////////////////////////// - template <class TValue> concept CErrorNestable = requires (TError& error, TValue&& operand) { diff --git a/yt/yt/core/ytree/convert-inl.h b/yt/yt/core/ytree/convert-inl.h index 694aca2d81f..0e3385ed5bf 100644 --- a/yt/yt/core/ytree/convert-inl.h +++ b/yt/yt/core/ytree/convert-inl.h @@ -182,12 +182,20 @@ T ConstructYTreeConvertibleObject() //////////////////////////////////////////////////////////////////////////////// -namespace { +} // namespace NYT::NYTree + +//////////////////////////////////////////////////////////////////////////////// + +namespace NYT::NConvertToImpl { //////////////////////////////////////////////////////////////////////////////// +namespace { + double ConvertYsonStringBaseToDouble(const NYson::TYsonStringBuf& yson) { + using namespace NYT::NYTree; + NYson::TTokenizer tokenizer(yson.AsStringBuf()); const auto& token = SkipAttributes(&tokenizer); switch (token.GetType()) { @@ -204,8 +212,12 @@ double ConvertYsonStringBaseToDouble(const NYson::TYsonStringBuf& yson) } } +//////////////////////////////////////////////////////////////////////////////// + TString ConvertYsonStringBaseToString(const NYson::TYsonStringBuf& yson) { + using namespace NYT::NYTree; + NYson::TTokenizer tokenizer(yson.AsStringBuf()); const auto& token = SkipAttributes(&tokenizer); switch (token.GetType()) { @@ -218,15 +230,7 @@ TString ConvertYsonStringBaseToString(const NYson::TYsonStringBuf& yson) } } -//////////////////////////////////////////////////////////////////////////////// - -} - -//////////////////////////////////////////////////////////////////////////////// - -} // namespace NYT::NYTree - -namespace NYT::NConvertToImpl { +} // namespace //////////////////////////////////////////////////////////////////////////////// @@ -314,25 +318,25 @@ IMPLEMENT_CHECKED_INTEGRAL_CONVERT_TO(ui8) template <> inline double TagInvoke(TTagInvokeTag<ConvertTo<double>>, const NYson::TYsonString& str) { - return NYTree::ConvertYsonStringBaseToDouble(str); + return ConvertYsonStringBaseToDouble(str); } template <> inline double TagInvoke(TTagInvokeTag<ConvertTo<double>>, const NYson::TYsonStringBuf& str) { - return NYTree::ConvertYsonStringBaseToDouble(str); + return ConvertYsonStringBaseToDouble(str); } template <> inline TString TagInvoke(TTagInvokeTag<ConvertTo<TString>>, const NYson::TYsonString& str) { - return NYTree::ConvertYsonStringBaseToString(str); + return ConvertYsonStringBaseToString(str); } template <> inline TString TagInvoke(TTagInvokeTag<ConvertTo<TString>>, const NYson::TYsonStringBuf& str) { - return NYTree::ConvertYsonStringBaseToString(str); + return ConvertYsonStringBaseToString(str); } //////////////////////////////////////////////////////////////////////////////// |
