diff --git a/serviceerror/convert.go b/serviceerror/convert.go index 603a176b..31926e01 100644 --- a/serviceerror/convert.go +++ b/serviceerror/convert.go @@ -93,6 +93,8 @@ func FromStatus(st *status.Status) error { switch errDetails.(type) { case *failure.MultiOperationExecutionAborted: return newMultiOperationAborted(st) + case *errordetails.WorkflowTaskCompletionBufferLostFailure: + return newWorkflowTaskCompletionBufferLost(st) default: return newAborted(st) } diff --git a/serviceerror/convert_test.go b/serviceerror/convert_test.go index 89c53344..5a86b70f 100644 --- a/serviceerror/convert_test.go +++ b/serviceerror/convert_test.go @@ -191,6 +191,22 @@ func TestMultiOperationAborted(t *testing.T) { require.True(t, proto.Equal(st.Proto(), reconstructedStatus.Proto())) } +func TestWorkflowTaskCompletionBufferLost(t *testing.T) { + err := serviceerror.NewWorkflowTaskCompletionBufferLost("buffer lost") + + st := serviceerror.ToStatus(err) + require.Equal(t, codes.Aborted, st.Code()) + require.Equal(t, err.Error(), st.Message()) + require.Len(t, st.Details(), 1) + + errFromStatus := serviceerror.FromStatus(st) + require.IsType(t, &serviceerror.WorkflowTaskCompletionBufferLost{}, errFromStatus) + require.Equal(t, err.Error(), errFromStatus.Error()) + + reconstructedStatus := serviceerror.ToStatus(errFromStatus) + require.True(t, proto.Equal(st.Proto(), reconstructedStatus.Proto())) +} + func TestFromWrapped(t *testing.T) { err := &serviceerror.PermissionDenied{ Message: "x is not allowed", diff --git a/serviceerror/workflow_task_completion_buffer_lost.go b/serviceerror/workflow_task_completion_buffer_lost.go new file mode 100644 index 00000000..f2b7d309 --- /dev/null +++ b/serviceerror/workflow_task_completion_buffer_lost.go @@ -0,0 +1,58 @@ +package serviceerror + +import ( + "fmt" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "go.temporal.io/api/errordetails/v1" +) + +type ( + // WorkflowTaskCompletionBufferLost represents a lost buffer during processing of a + // paginated workflow task completion request. Clients should restart pagination by + // resending all pages from page 0 with the same task token. + WorkflowTaskCompletionBufferLost struct { + Message string + st *status.Status + } +) + +// NewWorkflowTaskCompletionBufferLost returns a new WorkflowTaskCompletionBufferLost error. +func NewWorkflowTaskCompletionBufferLost(message string) error { + return &WorkflowTaskCompletionBufferLost{ + Message: message, + } +} + +// NewWorkflowTaskCompletionBufferLostf returns a new WorkflowTaskCompletionBufferLost error with a formatted message. +func NewWorkflowTaskCompletionBufferLostf(format string, args ...any) error { + return &WorkflowTaskCompletionBufferLost{ + Message: fmt.Sprintf(format, args...), + } +} + +// Error returns string message. +func (e *WorkflowTaskCompletionBufferLost) Error() string { + return e.Message +} + +func (e *WorkflowTaskCompletionBufferLost) Status() *status.Status { + if e.st != nil { + return e.st + } + + st := status.New(codes.Aborted, e.Message) + st, _ = st.WithDetails( + &errordetails.WorkflowTaskCompletionBufferLostFailure{}, + ) + return st +} + +func newWorkflowTaskCompletionBufferLost(st *status.Status) error { + return &WorkflowTaskCompletionBufferLost{ + Message: st.Message(), + st: st, + } +}