aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigory Reznikov <gritukan@nebius.com>2023-12-07 11:03:02 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2023-12-07 11:28:00 +0300
commitc9acd0d0c5306c53f3e81a780f2217870946be4d (patch)
tree8d80679e68531970bd449057ba23a44d2a2c9ece
parent87a9197de16375faef3babefc7d511be2b45f39a (diff)
downloadydb-c9acd0d0c5306c53f3e81a780f2217870946be4d.tar.gz
Avoid duplication of "original_error_depth" attribute during deep error reserialization
I hereby agree to the terms of the CLA available at: https://yandex.ru/legal/cla/?lang=en --- Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/218
-rw-r--r--yt/yt/core/misc/error.cpp8
-rw-r--r--yt/yt/core/misc/unittests/error_ut.cpp44
2 files changed, 50 insertions, 2 deletions
diff --git a/yt/yt/core/misc/error.cpp b/yt/yt/core/misc/error.cpp
index 33f5372356..17cf40583b 100644
--- a/yt/yt/core/misc/error.cpp
+++ b/yt/yt/core/misc/error.cpp
@@ -39,6 +39,10 @@ using NYT::ToProto;
////////////////////////////////////////////////////////////////////////////////
+constexpr TStringBuf OriginalErrorDepthAttribute = "original_error_depth";
+
+////////////////////////////////////////////////////////////////////////////////
+
void TErrorCode::Save(TStreamSaveContext& context) const
{
NYT::Save(context, Value_);
@@ -1155,9 +1159,9 @@ void Serialize(
.Item("trace_id").Value(error.GetTraceId())
.Item("span_id").Value(error.GetSpanId());
}
- if (depth > ErrorSerializationDepthLimit) {
+ if (depth > ErrorSerializationDepthLimit && !error.Attributes().Contains(OriginalErrorDepthAttribute)) {
fluent
- .Item("original_error_depth").Value(depth);
+ .Item(OriginalErrorDepthAttribute).Value(depth);
}
for (const auto& [key, value] : error.Attributes().ListPairs()) {
fluent
diff --git a/yt/yt/core/misc/unittests/error_ut.cpp b/yt/yt/core/misc/unittests/error_ut.cpp
index d2db8ff56c..905a35d414 100644
--- a/yt/yt/core/misc/unittests/error_ut.cpp
+++ b/yt/yt/core/misc/unittests/error_ut.cpp
@@ -421,6 +421,50 @@ TEST(TErrorTest, SerializationDepthLimit)
}
}
+TEST(TErrorTest, DoNotDuplicateOriginalErrorDepth)
+{
+ constexpr int Depth = 20;
+ ASSERT_GE(Depth, ErrorSerializationDepthLimit);
+
+ auto error = TError(TErrorCode(Depth), "error");
+ for (int i = Depth; i >= 2; --i) {
+ error = TError(TErrorCode(i), "error") << std::move(error);
+ }
+
+ auto errorYson = ConvertToYsonString(error);
+ error = ConvertTo<TError>(errorYson);
+
+ // Due to reserialization, error already contains "original_error_depth" attribute.
+ // It should not be duplicated after the next serialization.
+ error = TError(TErrorCode(1), "error") << std::move(error);
+
+ // Use intermediate conversion to test YSON parser depth limit simultaneously.
+ errorYson = ConvertToYsonString(error);
+ auto errorNode = ConvertTo<IMapNodePtr>(errorYson);
+
+ error = ConvertTo<TError>(errorYson);
+ for (int index = 0; index < ErrorSerializationDepthLimit - 1; ++index) {
+ ASSERT_FALSE(error.Attributes().Contains("original_error_depth"));
+ error = error.InnerErrors()[0];
+ }
+
+ const auto& children = error.InnerErrors();
+ ASSERT_EQ(std::ssize(children), Depth - ErrorSerializationDepthLimit + 1);
+ for (int index = 0; index < std::ssize(children); ++index) {
+ const auto& child = children[index];
+ if (index == 0) {
+ ASSERT_FALSE(child.Attributes().Contains("original_error_depth"));
+ } else {
+ ASSERT_TRUE(child.Attributes().Contains("original_error_depth"));
+ if (index == 1) {
+ ASSERT_EQ(child.Attributes().Get<i64>("original_error_depth"), index + ErrorSerializationDepthLimit);
+ } else {
+ ASSERT_EQ(child.Attributes().Get<i64>("original_error_depth"), index + ErrorSerializationDepthLimit - 1);
+ }
+ }
+ }
+}
+
TEST(TErrorTest, ErrorSkeletonStubImplementation)
{
TError error("foo");