Skip to content

Commit 2a65a7d

Browse files
committed
Expose OriginalFailure and use retryableOverride bool in serialization
1 parent 727c214 commit 2a65a7d

File tree

4 files changed

+47
-25
lines changed

4 files changed

+47
-25
lines changed

nexus/api.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ type OperationError struct {
7171
// The underlying cause for this error.
7272
Cause error
7373
// Set if this error is constructed from a failure object.
74-
originalFailure *Failure
74+
OriginalFailure *Failure
7575
}
7676

7777
// UnsuccessfulOperationError represents "failed" and "canceled" operation results.
@@ -229,7 +229,7 @@ type HandlerError struct {
229229
// RetryBehavior of this error. If not specified, retry behavior is determined from the error type.
230230
RetryBehavior HandlerErrorRetryBehavior
231231
// Set if this error is constructed from a failure object.
232-
originalFailure *Failure
232+
OriginalFailure *Failure
233233
}
234234

235235
// HandlerErrorf creates a [HandlerError] with the given type, using [fmt.Sprintf] to construct the message.
@@ -266,14 +266,16 @@ func (e *HandlerError) Retryable() bool {
266266
}
267267
}
268268

269-
func (e *HandlerError) retryBehaviorAsString() string {
269+
func (e *HandlerError) retryBehaviorAsOptionalBool() *bool {
270270
switch e.RetryBehavior {
271271
case HandlerErrorRetryBehaviorRetryable:
272-
return "true"
272+
ret := true
273+
return &ret
273274
case HandlerErrorRetryBehaviorNonRetryable:
274-
return "false"
275+
ret := false
276+
return &ret
275277
}
276-
return ""
278+
return nil
277279
}
278280

279281
// Error implements the error interface.

nexus/failure.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,18 @@ type FailureConverter interface {
5858
type knownErrorFailureConverter struct{}
5959

6060
type serializedHandlerError struct {
61-
Type string `json:"type,omitempty"`
62-
Retryable string `json:"retryable,omitempty"`
61+
Type string `json:"type,omitempty"`
62+
RetryableOverride *bool `json:"retryableOverride,omitempty"`
6363
}
6464

6565
func (e serializedHandlerError) RetryBehavior() HandlerErrorRetryBehavior {
66-
switch e.Retryable {
67-
case "true":
66+
if e.RetryableOverride == nil {
67+
return HandlerErrorRetryBehaviorUnspecified
68+
}
69+
if *e.RetryableOverride {
6870
return HandlerErrorRetryBehaviorRetryable
69-
case "false":
71+
} else {
7072
return HandlerErrorRetryBehaviorNonRetryable
71-
default:
72-
return HandlerErrorRetryBehaviorUnspecified
7373
}
7474
}
7575

@@ -96,16 +96,16 @@ func (e knownErrorFailureConverter) ErrorToFailure(err error) (Failure, error) {
9696
}
9797
return f, nil
9898
case *HandlerError:
99-
if typedErr.originalFailure != nil {
100-
return *typedErr.originalFailure, nil
99+
if typedErr.OriginalFailure != nil {
100+
return *typedErr.OriginalFailure, nil
101101
}
102102
// Temporary workaround for compatibility with old SDKs that don't support handler error messages.
103103
if typedErr.Message == "" && typedErr.Cause != nil {
104104
return e.ErrorToFailure(typedErr.Cause)
105105
}
106106
data := serializedHandlerError{
107-
Type: string(typedErr.Type),
108-
Retryable: typedErr.retryBehaviorAsString(),
107+
Type: string(typedErr.Type),
108+
RetryableOverride: typedErr.retryBehaviorAsOptionalBool(),
109109
}
110110
var details []byte
111111
details, err := json.Marshal(data)
@@ -131,8 +131,8 @@ func (e knownErrorFailureConverter) ErrorToFailure(err error) (Failure, error) {
131131

132132
return f, nil
133133
case *OperationError:
134-
if typedErr.originalFailure != nil {
135-
return *typedErr.originalFailure, nil
134+
if typedErr.OriginalFailure != nil {
135+
return *typedErr.OriginalFailure, nil
136136
}
137137
// Temporary workaround for compatibility with old SDKs that don't support operation error messages.
138138
if typedErr.Message == "" && typedErr.Cause != nil {
@@ -184,7 +184,7 @@ func (e knownErrorFailureConverter) FailureToError(f Failure) (error, error) {
184184
StackTrace: f.StackTrace,
185185
Type: HandlerErrorType(se.Type),
186186
RetryBehavior: se.RetryBehavior(),
187-
originalFailure: &f,
187+
OriginalFailure: &f,
188188
}
189189
if f.Cause != nil {
190190
he.Cause, err = e.FailureToError(*f.Cause)
@@ -203,7 +203,7 @@ func (e knownErrorFailureConverter) FailureToError(f Failure) (error, error) {
203203
Message: f.Message,
204204
StackTrace: f.StackTrace,
205205
State: OperationState(se.State),
206-
originalFailure: &f,
206+
OriginalFailure: &f,
207207
}
208208
if f.Cause != nil {
209209
oe.Cause, err = e.FailureToError(*f.Cause)

nexus/failure_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestFailureConverter_HandlerError(t *testing.T) {
5252
failure, err := defaultFailureConverter.ErrorToFailure(he)
5353
require.NoError(t, err)
5454
// Verify that the original failure is retained.
55-
he.originalFailure = &failure
55+
he.OriginalFailure = &failure
5656
actual, err := defaultFailureConverter.FailureToError(failure)
5757
require.NoError(t, err)
5858
require.Equal(t, he, actual)
@@ -68,6 +68,26 @@ func TestFailureConverter_HandlerError(t *testing.T) {
6868
require.Equal(t, he, actual)
6969
}
7070

71+
func TestFailureConverter_HandlerErrorRetryBehavior(t *testing.T) {
72+
he := HandlerErrorf(HandlerErrorTypeBadRequest, "foo")
73+
he.StackTrace = "stack"
74+
he.RetryBehavior = HandlerErrorRetryBehaviorRetryable
75+
failure, err := defaultFailureConverter.ErrorToFailure(he)
76+
require.NoError(t, err)
77+
// Verify that the original failure is retained.
78+
he.OriginalFailure = &failure
79+
actual, err := defaultFailureConverter.FailureToError(failure)
80+
require.NoError(t, err)
81+
require.Equal(t, he, actual)
82+
83+
// Serialize again and verify the original failure is used.
84+
failure, err = defaultFailureConverter.ErrorToFailure(he)
85+
require.NoError(t, err)
86+
actual, err = defaultFailureConverter.FailureToError(failure)
87+
require.NoError(t, err)
88+
require.Equal(t, he, actual)
89+
}
90+
7191
func TestFailureConverter_OperationError(t *testing.T) {
7292
cause := &FailureError{Failure: Failure{Message: "cause"}}
7393
oe := NewOperationCanceledError("foo")
@@ -76,7 +96,7 @@ func TestFailureConverter_OperationError(t *testing.T) {
7696
failure, err := defaultFailureConverter.ErrorToFailure(oe)
7797
require.NoError(t, err)
7898
// Verify that the original failure is retained.
79-
oe.originalFailure = &failure
99+
oe.OriginalFailure = &failure
80100
actual, err := defaultFailureConverter.FailureToError(failure)
81101
require.NoError(t, err)
82102
require.Equal(t, oe, actual)

nexus/server_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func TestWriteFailure_HandlerError(t *testing.T) {
4646
actual, err := defaultFailureConverter.FailureToError(failure)
4747
require.NoError(t, err)
4848
// Assign the original failure object before performing the comparison.
49-
he.originalFailure = &failure
49+
he.OriginalFailure = &failure
5050
require.Equal(t, he, actual)
5151
}
5252

@@ -69,6 +69,6 @@ func TestWriteFailure_OperationError(t *testing.T) {
6969
actual, err := defaultFailureConverter.FailureToError(failure)
7070
require.NoError(t, err)
7171
// Assign the original failure object before performing the comparison.
72-
oe.originalFailure = &failure
72+
oe.OriginalFailure = &failure
7373
require.Equal(t, oe, actual)
7474
}

0 commit comments

Comments
 (0)