From 95c81bd04a4b8b13636dc5cc4a11d7a0a6706f06 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Thu, 11 May 2023 16:35:22 -0700 Subject: [PATCH] Properly store the original failurepb on decode (#1101) --- internal/error_test.go | 56 +++++++++++++++++++++++++++++++++++ internal/failure_converter.go | 6 ++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/internal/error_test.go b/internal/error_test.go index f2c0ac02e..7a815be35 100644 --- a/internal/error_test.go +++ b/internal/error_test.go @@ -667,6 +667,62 @@ func Test_convertErrorToFailure_EncodeMessage(t *testing.T) { require.Equal("cause error", applicationErr.Error()) } +func Test_EncodeDecodeEncodeMessage(t *testing.T) { + require := require.New(t) + + fc := NewDefaultFailureConverter(DefaultFailureConverterOptions{ + DataConverter: converter.GetDefaultDataConverter(), + EncodeCommonAttributes: true, + }) + + subAppErr := NewApplicationError("sub message", "sub customType", true, errors.New("cause error"), "sub details", 2208) + err := NewApplicationError("message", "customType", true, subAppErr, "details", 2208) + f := fc.ErrorToFailure(err) + // Check main error is encoded + require.Equal("Encoded failure", f.GetMessage()) + require.Equal("", f.GetStackTrace()) + require.Equal("customType", f.GetApplicationFailureInfo().GetType()) + require.Equal(true, f.GetApplicationFailureInfo().GetNonRetryable()) + require.Equal([]byte(`"details"`), f.GetApplicationFailureInfo().GetDetails().GetPayloads()[0].GetData()) + require.Equal([]byte(`2208`), f.GetApplicationFailureInfo().GetDetails().GetPayloads()[1].GetData()) + // Check sub error in encoded + require.Equal("Encoded failure", f.GetCause().GetMessage()) + require.Equal("", f.GetCause().GetStackTrace()) + require.Equal("sub customType", f.GetCause().GetApplicationFailureInfo().GetType()) + require.Equal(true, f.GetCause().GetApplicationFailureInfo().GetNonRetryable()) + // Check the sub sub error is encoded + require.Equal("Encoded failure", f.GetCause().GetCause().GetMessage()) + require.Equal("", f.GetCause().GetCause().GetApplicationFailureInfo().GetType()) + require.Nil(f.GetCause().GetCause().GetCause()) + + err2 := fc.FailureToError(f) + var applicationErr *ApplicationError + require.True(errors.As(err2, &applicationErr)) + require.Equal("message (type: customType, retryable: false): sub message (type: sub customType, retryable: false): cause error", applicationErr.Error()) + + subErr := errors.Unwrap(err2) + require.True(errors.As(subErr, &applicationErr)) + require.Equal("sub message (type: sub customType, retryable: false): cause error", applicationErr.Error()) + + subSubErr := errors.Unwrap(subErr) + require.True(errors.As(subSubErr, &applicationErr)) + require.Equal("cause error", applicationErr.Error()) + // Check main error is re-encoded properly + f = fc.ErrorToFailure(err2) + require.Equal("Encoded failure", f.GetMessage()) + require.Equal("", f.GetStackTrace()) + require.Equal("customType", f.GetApplicationFailureInfo().GetType()) + require.Equal(true, f.GetCause().GetApplicationFailureInfo().GetNonRetryable()) + // Check sub error in re-encoded + require.Equal("Encoded failure", f.GetCause().GetMessage()) + require.Equal("", f.GetCause().GetStackTrace()) + require.Equal("sub customType", f.GetCause().GetApplicationFailureInfo().GetType()) + // Check the sub sub error is encoded + require.Equal("Encoded failure", f.GetCause().GetCause().GetMessage()) + require.Equal("", f.GetCause().GetCause().GetApplicationFailureInfo().GetType()) + require.Nil(f.GetCause().GetCause().GetCause()) +} + func Test_convertErrorToFailure_EncodeStackTrace(t *testing.T) { require := require.New(t) fc := NewDefaultFailureConverter(DefaultFailureConverterOptions{ diff --git a/internal/failure_converter.go b/internal/failure_converter.go index 2bb08607a..553866608 100644 --- a/internal/failure_converter.go +++ b/internal/failure_converter.go @@ -25,6 +25,7 @@ package internal import ( "errors" + "github.com/gogo/protobuf/proto" commonpb "go.temporal.io/api/common/v1" failurepb "go.temporal.io/api/failure/v1" "go.temporal.io/sdk/converter" @@ -174,7 +175,8 @@ func (dfc *DefaultFailureConverter) FailureToError(failure *failurepb.Failure) e if failure == nil { return nil } - + // Copy the original future to pass to the failureHolder + originalFailure := proto.Clone(failure).(*failurepb.Failure) converter.DecodeCommonFailureAttributes(dfc.dataConverter, failure) message := failure.GetMessage() @@ -243,7 +245,7 @@ func (dfc *DefaultFailureConverter) FailureToError(failure *failurepb.Failure) e } if fh, ok := err.(failureHolder); ok { - fh.setFailure(failure) + fh.setFailure(originalFailure) } return err