Files
ebef6c2be8 Validate activity task stamps before reuse (#8536)
## Summary
- add the activity task stamp to `IsActivityTaskValidRequest` and
generated API stubs
- require history's activity validation logic to match the stored stamp
- plumb the stamp from matching task validation and cover the new
behavior with tests
- increment activity stamps for each retry attempt and extend tests for
paused retries

## Testing
- `GOTOOLCHAIN=local go test -tags test_dep ./service/history/workflow
-run TestRetryActivity` *(fails: go.mod requires go >= 1.25.0 and local
toolchain is go1.24.3)*

------
https://chatgpt.com/codex/tasks/task_b_68faffae045c832c9d8220bcbe50bac7

---------

Co-authored-by: Michael Youssef <[email protected]>
2025-11-04 00:27:12 +00:00

65 lines
1.7 KiB
Go

package isactivitytaskvalid
import (
"context"
"go.temporal.io/server/api/historyservice/v1"
"go.temporal.io/server/common"
"go.temporal.io/server/common/definition"
"go.temporal.io/server/service/history/api"
"go.temporal.io/server/service/history/consts"
historyi "go.temporal.io/server/service/history/interfaces"
)
func Invoke(
ctx context.Context,
req *historyservice.IsActivityTaskValidRequest,
shardContext historyi.ShardContext,
workflowConsistencyChecker api.WorkflowConsistencyChecker,
) (resp *historyservice.IsActivityTaskValidResponse, retError error) {
isValid := false
err := api.GetAndUpdateWorkflowWithNew(
ctx,
req.Clock,
definition.NewWorkflowKey(
req.NamespaceId,
req.Execution.WorkflowId,
req.Execution.RunId,
),
func(workflowLease api.WorkflowLease) (*api.UpdateWorkflowAction, error) {
isTaskValid, err := isActivityTaskValid(workflowLease, req.ScheduledEventId, req.GetStamp())
if err != nil {
return nil, err
}
isValid = isTaskValid
return &api.UpdateWorkflowAction{
Noop: true,
CreateWorkflowTask: false,
}, nil
},
nil,
shardContext,
workflowConsistencyChecker,
)
return &historyservice.IsActivityTaskValidResponse{
IsValid: isValid,
}, err
}
func isActivityTaskValid(
workflowLease api.WorkflowLease,
scheduledEventID int64,
stamp int32,
) (bool, error) {
mutableState := workflowLease.GetMutableState()
if !mutableState.IsWorkflowExecutionRunning() {
return false, consts.ErrWorkflowCompleted
}
ai, ok := mutableState.GetActivityInfo(scheduledEventID)
if ok && ai.StartedEventId == common.EmptyEventID && ai.GetStamp() == stamp {
return true, nil
}
return false, nil
}