Skip to content

Commit 41e9b33

Browse files
authoredDec 9, 2024··
Tweak Update-with-Start error reporting (#1746)
1 parent 7828e06 commit 41e9b33

File tree

2 files changed

+82
-54
lines changed

2 files changed

+82
-54
lines changed
 

Diff for: ‎internal/internal_workflow_client.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,7 @@ func (w *workflowClientInterceptor) UpdateWithStartWorkflow(
17611761
// Create update request
17621762
updateReq, err := w.createUpdateWorkflowRequest(ctx, updateInput)
17631763
if err != nil {
1764-
return nil, fmt.Errorf("%w: %w", errInvalidWithStartWorkflowOperation, err)
1764+
return nil, err
17651765
}
17661766
if updateReq.WorkflowExecution.WorkflowId == "" {
17671767
updateReq.WorkflowExecution.WorkflowId = startReq.WorkflowId
@@ -1800,7 +1800,7 @@ func (w *workflowClientInterceptor) UpdateWithStartWorkflow(
18001800
}
18011801
handle, err := w.updateHandleFromResponse(ctx, updateReq.WaitPolicy.LifecycleStage, updateResp)
18021802
if err != nil {
1803-
return nil, fmt.Errorf("%w: %w", errInvalidWithStartWorkflowOperation, err)
1803+
return nil, err
18041804
}
18051805
return handle, nil
18061806
}
@@ -1862,27 +1862,31 @@ func (w *workflowClientInterceptor) updateWithStartWorkflow(
18621862
}
18631863

18641864
var abortedErr *serviceerror.MultiOperationAborted
1865-
startErr := errors.New("failed to start workflow")
18661865
for i, opReq := range multiRequest.Operations {
18671866
// if an operation error is of type MultiOperationAborted, it means it was only aborted because
18681867
// of another operation's error and is therefore not interesting or helpful
18691868
opErr := multiErr.OperationErrors()[i]
1869+
if opErr == nil {
1870+
continue
1871+
}
18701872

18711873
switch t := opReq.Operation.(type) {
18721874
case *workflowservice.ExecuteMultiOperationRequest_Operation_StartWorkflow:
18731875
if !errors.As(opErr, &abortedErr) {
1874-
startErr = opErr
1876+
return nil, fmt.Errorf("failed workflow start: %w", opErr)
18751877
}
18761878
case *workflowservice.ExecuteMultiOperationRequest_Operation_UpdateWorkflow:
18771879
if !errors.As(opErr, &abortedErr) {
1878-
startErr = fmt.Errorf("%w: %w", errInvalidWithStartWorkflowOperation, opErr)
1880+
return nil, fmt.Errorf("failed workflow update: %w", opErr)
18791881
}
18801882
default:
18811883
// this would only happen if a case statement for a newly added operation is missing above
18821884
return nil, fmt.Errorf("%w: %T", errUnsupportedOperation, t)
18831885
}
18841886
}
1885-
return nil, startErr
1887+
1888+
// this should never happen
1889+
return nil, errors.New(multiErr.Error())
18861890
} else if err != nil {
18871891
return nil, err
18881892
}

Diff for: ‎internal/internal_workflow_client_test.go

+72-48
Original file line numberDiff line numberDiff line change
@@ -1113,30 +1113,80 @@ func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_Abort() {
11131113
}
11141114
}
11151115

1116-
func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_NonMultiOperationError() {
1117-
s.workflowServiceClient.EXPECT().
1118-
ExecuteMultiOperation(gomock.Any(), gomock.Any(), gomock.Any()).
1119-
Return(nil, serviceerror.NewInternal("internal error")).Times(1)
1116+
func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_Errors() {
1117+
tests := []struct {
1118+
name string
1119+
returnedErr error
1120+
expectedErr string
1121+
}{
1122+
{
1123+
name: "NonMultiOperationError",
1124+
returnedErr: serviceerror.NewInternal("internal error"),
1125+
expectedErr: "internal error",
1126+
},
1127+
{
1128+
name: "CountMismatch",
1129+
returnedErr: serviceerror.NewMultiOperationExecution("Error", []error{}),
1130+
expectedErr: "invalid server response: 0 instead of 2 operation errors",
1131+
},
1132+
{
1133+
name: "NilErrors",
1134+
returnedErr: serviceerror.NewMultiOperationExecution("MultiOperation failed", []error{
1135+
nil, nil,
1136+
}),
1137+
expectedErr: "MultiOperation failed",
1138+
},
1139+
{
1140+
name: "StartOperationError",
1141+
returnedErr: serviceerror.NewMultiOperationExecution("MultiOperation failed", []error{
1142+
serviceerror.NewInvalidArgument("invalid Start"),
1143+
serviceerror.NewMultiOperationAborted("aborted Update"),
1144+
}),
1145+
expectedErr: "failed workflow start: invalid Start",
1146+
},
1147+
{
1148+
name: "UpdateOperationError_AbortedStart",
1149+
returnedErr: serviceerror.NewMultiOperationExecution("MultiOperation failed", []error{
1150+
serviceerror.NewMultiOperationAborted("aborted Start"),
1151+
serviceerror.NewInvalidArgument("invalid Update"),
1152+
}),
1153+
expectedErr: "failed workflow update: invalid Update",
1154+
},
1155+
{
1156+
name: "UpdateOperationError_SuccessfulStart",
1157+
returnedErr: serviceerror.NewMultiOperationExecution("MultiOperation failed", []error{
1158+
nil, // ie successful start
1159+
serviceerror.NewInvalidArgument("bad Update"),
1160+
}),
1161+
expectedErr: "failed workflow update: bad Update",
1162+
},
1163+
}
11201164

1121-
startOp := s.workflowClient.NewWithStartWorkflowOperation(
1122-
StartWorkflowOptions{
1123-
ID: workflowID,
1124-
WorkflowIDConflictPolicy: enumspb.WORKFLOW_ID_CONFLICT_POLICY_FAIL,
1125-
TaskQueue: taskqueue,
1126-
}, workflowType,
1127-
)
1165+
for _, tt := range tests {
1166+
s.Run(tt.name, func() {
1167+
s.workflowServiceClient.EXPECT().
1168+
ExecuteMultiOperation(gomock.Any(), gomock.Any(), gomock.Any()).
1169+
Return(nil, tt.returnedErr).Times(1)
11281170

1129-
_, err := s.workflowClient.UpdateWithStartWorkflow(
1130-
context.Background(),
1131-
UpdateWithStartWorkflowOptions{
1132-
UpdateOptions: UpdateWorkflowOptions{
1133-
UpdateName: "update",
1134-
WaitForStage: WorkflowUpdateStageCompleted,
1135-
},
1136-
StartWorkflowOperation: startOp,
1137-
},
1138-
)
1139-
s.ErrorContains(err, "internal error")
1171+
_, err := s.workflowClient.UpdateWithStartWorkflow(
1172+
context.Background(),
1173+
UpdateWithStartWorkflowOptions{
1174+
UpdateOptions: UpdateWorkflowOptions{
1175+
UpdateName: "update",
1176+
WaitForStage: WorkflowUpdateStageCompleted,
1177+
},
1178+
StartWorkflowOperation: s.workflowClient.NewWithStartWorkflowOperation(
1179+
StartWorkflowOptions{
1180+
ID: workflowID,
1181+
WorkflowIDConflictPolicy: enumspb.WORKFLOW_ID_CONFLICT_POLICY_FAIL,
1182+
TaskQueue: taskqueue,
1183+
}, workflowType,
1184+
),
1185+
},
1186+
)
1187+
s.EqualError(err, tt.expectedErr)
1188+
})
1189+
}
11401190
}
11411191

11421192
func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_ServerResponseCountMismatch() {
@@ -1167,32 +1217,6 @@ func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_ServerResponseCountMism
11671217
s.ErrorContains(err, "invalid server response: 0 instead of 2 operation results")
11681218
}
11691219

1170-
func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_ServerErrorResponseCountMismatch() {
1171-
s.workflowServiceClient.EXPECT().
1172-
ExecuteMultiOperation(gomock.Any(), gomock.Any(), gomock.Any()).
1173-
Return(nil, serviceerror.NewMultiOperationExecution("Error", []error{})).Times(1)
1174-
1175-
startOp := s.workflowClient.NewWithStartWorkflowOperation(
1176-
StartWorkflowOptions{
1177-
ID: workflowID,
1178-
WorkflowIDConflictPolicy: enumspb.WORKFLOW_ID_CONFLICT_POLICY_FAIL,
1179-
TaskQueue: taskqueue,
1180-
}, workflowType,
1181-
)
1182-
1183-
_, err := s.workflowClient.UpdateWithStartWorkflow(
1184-
context.Background(),
1185-
UpdateWithStartWorkflowOptions{
1186-
UpdateOptions: UpdateWorkflowOptions{
1187-
UpdateName: "update",
1188-
WaitForStage: WorkflowUpdateStageCompleted,
1189-
},
1190-
StartWorkflowOperation: startOp,
1191-
},
1192-
)
1193-
s.ErrorContains(err, "invalid server response: 0 instead of 2 operation errors")
1194-
}
1195-
11961220
func (s *workflowRunSuite) TestExecuteWorkflowWithUpdate_ServerStartResponseTypeMismatch() {
11971221
s.workflowServiceClient.EXPECT().
11981222
ExecuteMultiOperation(gomock.Any(), gomock.Any(), gomock.Any()).

0 commit comments

Comments
 (0)
Please sign in to comment.