aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarkady-e1ppa <arkady-e1ppa@yandex-team.com>2023-12-05 14:44:02 +0300
committerarkady-e1ppa <arkady-e1ppa@yandex-team.com>2023-12-05 15:47:34 +0300
commitd7830d26621b08d508ba92fccf9e4971cc8ded61 (patch)
tree231e17a9b97711289a1eb59a7fad4e140e26c515
parent496b43dd6e141cae303b3a4c727cabc0d04ed1ae (diff)
downloadydb-d7830d26621b08d508ba92fccf9e4971cc8ded61.tar.gz
YT-20547: OperationId is strongly typed
-rw-r--r--library/cpp/yt/misc/strong_typedef-inl.h32
-rw-r--r--library/cpp/yt/misc/strong_typedef.h12
-rw-r--r--library/cpp/yt/misc/wrapper_traits-inl.h109
-rw-r--r--library/cpp/yt/misc/wrapper_traits.h73
-rw-r--r--ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp2
-rw-r--r--yt/yt/client/driver/scheduler_commands.h5
-rw-r--r--yt/yt/client/job_tracker_client/public.h3
-rw-r--r--yt/yt/client/object_client/public.h3
-rw-r--r--yt/yt/client/scheduler/operation_id_or_alias.cpp2
-rw-r--r--yt/yt/core/ytree/yson_serializable-inl.h5
-rw-r--r--yt/yt/core/ytree/yson_struct_detail-inl.h6
11 files changed, 235 insertions, 17 deletions
diff --git a/library/cpp/yt/misc/strong_typedef-inl.h b/library/cpp/yt/misc/strong_typedef-inl.h
index 00f0cc0cc8..d24c76c1dd 100644
--- a/library/cpp/yt/misc/strong_typedef-inl.h
+++ b/library/cpp/yt/misc/strong_typedef-inl.h
@@ -4,6 +4,8 @@
#include "strong_typedef.h"
#endif
+#include "wrapper_traits.h"
+
#include <util/generic/strbuf.h>
#include <functional>
@@ -62,7 +64,8 @@ constexpr T&& TStrongTypedef<T, TTag>::Underlying() &&
template <class T, class TTag>
constexpr bool TStrongTypedef<T, TTag>::operator==(const TStrongTypedef& rhs) const
- noexcept(std::same_as<T, void> || noexcept(Underlying_ == rhs.Underlying_))
+ noexcept(noexcept(Underlying_ == rhs.Underlying_))
+ requires std::equality_comparable<T>
{
//! NB: We add a constexpr branch to keep constexprness of the function
//! without making extra specializations explicitly.
@@ -75,7 +78,8 @@ constexpr bool TStrongTypedef<T, TTag>::operator==(const TStrongTypedef& rhs) co
template <class T, class TTag>
constexpr auto TStrongTypedef<T, TTag>::operator<=>(const TStrongTypedef& rhs) const
- noexcept(std::same_as<T, void> || noexcept(Underlying_ <=> rhs.Underlying_))
+ noexcept(noexcept(Underlying_ <=> rhs.Underlying_))
+ requires std::three_way_comparable<T>
{
//! NB: We add a constexpr branch to keep constexprness of the function
//! without making extra specializations explicitly.
@@ -111,7 +115,7 @@ struct TStrongTypedefTraits<TStrongTypedef<T, TTag>>
////////////////////////////////////////////////////////////////////////////////
template <class T, class TChar>
- requires TStrongTypedefTraits<T>::IsStrongTypedef
+ requires CStrongTypedef<T>
bool TryFromStringImpl(const TChar* data, size_t size, T& value)
{
return TryFromString(data, size, value.Underlying());
@@ -130,6 +134,28 @@ void FormatValue(TStringBuilderBase* builder, const TStrongTypedef<T, TTag>& val
////////////////////////////////////////////////////////////////////////////////
+template <class T, class TTag>
+struct TBasicWrapperTraits<TStrongTypedef<T, TTag>>
+{
+ static constexpr bool IsTrivialWrapper = false;
+
+ using TUnwrapped = T;
+
+ static constexpr bool HasValue(const TStrongTypedef<T, TTag>&) noexcept
+ {
+ return true;
+ }
+
+ template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, TStrongTypedef<T, TTag>>
+ static constexpr decltype(auto) Unwrap(U&& wrapper) noexcept
+ {
+ return std::forward<U>(wrapper).Underlying();
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
} // namespace NYT
namespace std {
diff --git a/library/cpp/yt/misc/strong_typedef.h b/library/cpp/yt/misc/strong_typedef.h
index 8ed0810b53..3b093026a4 100644
--- a/library/cpp/yt/misc/strong_typedef.h
+++ b/library/cpp/yt/misc/strong_typedef.h
@@ -33,10 +33,12 @@ public:
constexpr explicit operator T&();
constexpr bool operator==(const TStrongTypedef& rhs) const
- noexcept(std::same_as<T, void> || noexcept(Underlying_ == rhs.Underlying_));
+ noexcept(noexcept(Underlying_ == rhs.Underlying_))
+ requires std::equality_comparable<T>;
constexpr auto operator<=>(const TStrongTypedef& rhs) const
- noexcept(std::same_as<T, void> || noexcept(Underlying_ <=> rhs.Underlying_));
+ noexcept(noexcept(Underlying_ <=> rhs.Underlying_))
+ requires std::three_way_comparable<T>;
explicit operator bool() const
noexcept(noexcept(static_cast<bool>(Underlying_)));
@@ -61,6 +63,12 @@ private:
{ }; \
using T = ::NYT::TStrongTypedef<TUnderlying, T##Tag>; \
+template <class T>
+struct TStrongTypedefTraits;
+
+template <class T>
+concept CStrongTypedef = TStrongTypedefTraits<T>::IsStrongTypedef;
+
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT
diff --git a/library/cpp/yt/misc/wrapper_traits-inl.h b/library/cpp/yt/misc/wrapper_traits-inl.h
new file mode 100644
index 0000000000..88d1af5945
--- /dev/null
+++ b/library/cpp/yt/misc/wrapper_traits-inl.h
@@ -0,0 +1,109 @@
+#ifndef WRAPPER_TRAITS_INL_H_
+#error "Direct inclusion of this file is not allowed, include wrapper_traits.h"
+// For the sake of sane code completion.
+#include "wrapper_traits.h"
+#endif
+
+#include <library/cpp/yt/assert/assert.h>
+
+#include <optional>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+ requires std::is_object_v<T>
+template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, T>
+constexpr decltype(auto) TBasicWrapperTraits<T>::Unwrap(U&& wrapper) noexcept
+{
+ return std::forward<U>(wrapper);
+}
+
+template <class T>
+ requires std::is_object_v<T>
+constexpr bool TBasicWrapperTraits<T>::HasValue(const T&) noexcept
+{
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+ requires std::is_object_v<T>
+template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, T>
+constexpr decltype(auto) TWrapperTraits<T>::Unwrap(U&& wrapper)
+{
+ YT_VERIFY(HasValue(wrapper));
+ return TBasicWrapperTraits<T>::Unwrap(std::forward<U>(wrapper));
+}
+
+template <class T>
+ requires std::is_object_v<T>
+template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, T>
+constexpr decltype(auto) TWrapperTraits<T>::RecursiveUnwrap(U&& wrapper)
+{
+ using TDecayedU = std::remove_cvref_t<U>;
+ using TTraits = TWrapperTraits<TDecayedU>;
+ using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>;
+
+ if constexpr (CNonTrivialWrapper<TDecayedU>) {
+ return TInnerTraits::RecursiveUnwrap(TTraits::Unwrap(std::forward<U>(wrapper)));
+ } else {
+ return TTraits::Unwrap(std::forward<U>(wrapper));
+ }
+}
+
+template <class T>
+ requires std::is_object_v<T>
+constexpr bool TWrapperTraits<T>::HasValue(const T& wrapper) noexcept
+{
+ return TBasicWrapperTraits<T>::HasValue(wrapper);
+}
+
+template <class T>
+ requires std::is_object_v<T>
+constexpr bool TWrapperTraits<T>::RecursiveHasValue(const T& wrapper) noexcept
+{
+ using TTraits = TWrapperTraits<T>;
+ using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>;
+
+ if constexpr (CNonTrivialWrapper<T>) {
+ return TTraits::HasValue(wrapper) && TInnerTraits::HasValue(TTraits::Unwrap(wrapper));
+ } else {
+ return TTraits::HasValue(wrapper);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Some standard library specializations
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+struct TBasicWrapperTraits<std::optional<T>>
+{
+ static constexpr bool IsTrivialWrapper = false;
+
+ using TUnwrapped = T;
+
+ static constexpr bool HasValue(const std::optional<T>& optional) noexcept
+ {
+ return optional.has_value();
+ }
+
+ template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, std::optional<T>>
+ static decltype(auto) Unwrap(U&& optional)
+ {
+ return *std::forward<U>(optional);
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/library/cpp/yt/misc/wrapper_traits.h b/library/cpp/yt/misc/wrapper_traits.h
new file mode 100644
index 0000000000..61a97b8ea4
--- /dev/null
+++ b/library/cpp/yt/misc/wrapper_traits.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <utility>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Default implementation of wrapper traits you can specialize for your type
+template <class T>
+ requires std::is_object_v<T>
+struct TBasicWrapperTraits
+{
+ static constexpr bool IsTrivialWrapper = true;
+
+ using TUnwrapped = T;
+
+ //! Default implementations just forward the argument
+ template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, T>
+ static constexpr decltype(auto) Unwrap(U&& wrapper) noexcept;
+
+ static constexpr bool HasValue(const T& wrapper) noexcept;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+//! Represents common denominator of every single value wrapper
+template <class T>
+ requires std::is_object_v<T>
+struct TWrapperTraits
+{
+public:
+ static constexpr bool IsTrivialWrapper = TBasicWrapperTraits<T>::IsTrivialWrapper;
+
+ using TWrapped = T;
+ using TUnwrapped = typename TBasicWrapperTraits<T>::TUnwrapped;
+
+ static constexpr bool HasValue(const T& wrapper) noexcept;
+
+ static constexpr bool RecursiveHasValue(const T& wrapper) noexcept;
+
+ template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, T>
+ static constexpr decltype(auto) Unwrap(U&& wrapper);
+
+ template <class U>
+ requires std::same_as<std::remove_cvref_t<U>, T>
+ static constexpr decltype(auto) RecursiveUnwrap(U&& wrapper);
+
+ using TRecursiveUnwrapped = std::remove_cvref_t<decltype(TWrapperTraits<T>::RecursiveUnwrap(std::declval<T>()))>;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+concept CNonTrivialWrapper =
+ (!TBasicWrapperTraits<T>::IsTrivialWrapper) &&
+ requires (T& wrapper, const T& const_wrapper) {
+ typename TBasicWrapperTraits<T>::TUnwrapped;
+ { TBasicWrapperTraits<T>::Unwrap(wrapper) } -> std::same_as<typename TBasicWrapperTraits<T>::TUnwrapped&>;
+ { TBasicWrapperTraits<T>::Unwrap(std::move(wrapper)) } -> std::same_as<typename TBasicWrapperTraits<T>::TUnwrapped&&>;
+ { TBasicWrapperTraits<T>::Unwrap(const_wrapper) } -> std::same_as<const typename TBasicWrapperTraits<T>::TUnwrapped&>;
+ { TBasicWrapperTraits<T>::HasValue(const_wrapper) } -> std::same_as<bool>;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+#define WRAPPER_TRAITS_INL_H_
+#include "wrapper_traits-inl.h"
+#undef WRAPPER_TRAITS_INL_H_
diff --git a/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp b/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp
index d8a7a70a39..37e401aa90 100644
--- a/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp
+++ b/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp
@@ -58,7 +58,7 @@ namespace NYql {
, ClusterName(clusterName)
, YtWrapper(ytWrapper)
, ParentId(parentId)
- , OperationId(NYT::NScheduler::TOperationId::FromString(operationId))
+ , OperationId(NYT::NScheduler::TOperationId(NYT::TGuid::FromString(operationId)))
, MutationId(mutationId)
, Counters(counters)
{ }
diff --git a/yt/yt/client/driver/scheduler_commands.h b/yt/yt/client/driver/scheduler_commands.h
index 28f68fd757..b0daea15fb 100644
--- a/yt/yt/client/driver/scheduler_commands.h
+++ b/yt/yt/client/driver/scheduler_commands.h
@@ -35,8 +35,9 @@ public:
.Default();
registrar.Postprocessor([] (TThis* command) {
- if (!command->OperationId.IsEmpty() && command->OperationAlias.operator bool() ||
- command->OperationId.IsEmpty() && !command->OperationAlias.operator bool())
+ auto operationId = command->OperationId;
+ if (operationId && command->OperationAlias.has_value() ||
+ !operationId && !command->OperationAlias.has_value())
{
THROW_ERROR_EXCEPTION("Exactly one of \"operation_id\" and \"operation_alias\" should be set")
<< TErrorAttribute("operation_id", command->OperationId)
diff --git a/yt/yt/client/job_tracker_client/public.h b/yt/yt/client/job_tracker_client/public.h
index 984fa0fcec..5e1886f458 100644
--- a/yt/yt/client/job_tracker_client/public.h
+++ b/yt/yt/client/job_tracker_client/public.h
@@ -12,7 +12,8 @@ YT_DEFINE_STRONG_TYPEDEF(TJobId, TGuid);
extern const TJobId NullJobId;
-using TOperationId = TGuid;
+YT_DEFINE_STRONG_TYPEDEF(TOperationId, TGuid);
+
extern const TOperationId NullOperationId;
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/client/object_client/public.h b/yt/yt/client/object_client/public.h
index d8f98323f6..1d002cdc36 100644
--- a/yt/yt/client/object_client/public.h
+++ b/yt/yt/client/object_client/public.h
@@ -5,6 +5,7 @@
#include <library/cpp/yt/misc/hash.h>
#include <yt/yt/client/election/public.h>
+#include <yt/yt/client/job_tracker_client/public.h>
#include <library/cpp/yt/misc/strong_typedef.h>
@@ -345,7 +346,7 @@ constexpr EObjectType MaxErasureJournalChunkPartType = EObjectType::ErasureJourn
using TTransactionId = TObjectId;
constexpr TTransactionId NullTransactionId = {};
-using TOperationId = TObjectId;
+using NJobTrackerClient::TOperationId;
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/client/scheduler/operation_id_or_alias.cpp b/yt/yt/client/scheduler/operation_id_or_alias.cpp
index 4a64364815..5711c11c69 100644
--- a/yt/yt/client/scheduler/operation_id_or_alias.cpp
+++ b/yt/yt/client/scheduler/operation_id_or_alias.cpp
@@ -24,7 +24,7 @@ TOperationIdOrAlias TOperationIdOrAlias::FromString(TString operationIdOrAlias)
if (!operationIdOrAlias.empty() && operationIdOrAlias[0] == '*') {
return TOperationIdOrAlias(operationIdOrAlias);
} else {
- return TOperationIdOrAlias(TOperationId::FromString(operationIdOrAlias));
+ return TOperationIdOrAlias(TOperationId(TGuid::FromString(operationIdOrAlias)));
}
}
diff --git a/yt/yt/core/ytree/yson_serializable-inl.h b/yt/yt/core/ytree/yson_serializable-inl.h
index 7269174a30..b28578fd39 100644
--- a/yt/yt/core/ytree/yson_serializable-inl.h
+++ b/yt/yt/core/ytree/yson_serializable-inl.h
@@ -21,6 +21,7 @@
#include <yt/yt/core/actions/bind.h>
#include <library/cpp/yt/misc/enum.h>
+#include <library/cpp/yt/misc/wrapper_traits.h>
#include <util/datetime/base.h>
@@ -622,9 +623,7 @@ concept SupportsDontSerializeDefaultImpl =
template <class T>
concept SupportsDontSerializeDefault =
- SupportsDontSerializeDefaultImpl<T> ||
- TStdOptionalTraits<T>::IsStdOptional &&
- SupportsDontSerializeDefaultImpl<typename TStdOptionalTraits<T>::TValueType>;
+ SupportsDontSerializeDefaultImpl<typename TWrapperTraits<T>::TRecursiveUnwrapped>;
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/ytree/yson_struct_detail-inl.h b/yt/yt/core/ytree/yson_struct_detail-inl.h
index ce7ded1def..bee8d63aeb 100644
--- a/yt/yt/core/ytree/yson_struct_detail-inl.h
+++ b/yt/yt/core/ytree/yson_struct_detail-inl.h
@@ -9,6 +9,8 @@
#include <yt/yt/core/yson/token_writer.h>
+#include <library/cpp/yt/misc/wrapper_traits.h>
+
namespace NYT::NYTree {
////////////////////////////////////////////////////////////////////////////////
@@ -31,9 +33,7 @@ concept SupportsDontSerializeDefaultImpl =
template <class T>
concept SupportsDontSerializeDefault =
- SupportsDontSerializeDefaultImpl<T> ||
- TStdOptionalTraits<T>::IsStdOptional &&
- SupportsDontSerializeDefaultImpl<typename TStdOptionalTraits<T>::TValueType>;
+ SupportsDontSerializeDefaultImpl<typename TWrapperTraits<T>::TRecursiveUnwrapped>;
////////////////////////////////////////////////////////////////////////////////