Add activity outcome in start activity response#10359
Draft
ks-temporal wants to merge 3 commits into
Draft
Conversation
In StartActivityExecution if IncludeOutcome is set in the request and the activity is already started, and the outcome is available, then instead of returning AlreadyStarted error, return success with the outcome and runID of the already started activity. Before adding completion callbacks, do the same check, and avoid adding callbacks on completed activity, as it will fail, but return success with outcome of the completed activity. Refactor the check and add to Activity function to allow unit test.
fretz12
reviewed
May 22, 2026
Comment on lines
+303
to
+317
| func (a *Activity) getOutcomeOrAddCallbacks( | ||
| ctx chasm.MutableContext, input getOutcomeOrAddCallbacksInput, | ||
| ) (*apiactivitypb.ActivityExecutionOutcome, error) { | ||
| var outcome *apiactivitypb.ActivityExecutionOutcome | ||
|
|
||
| if input.includeOutcome { | ||
| outcome = a.outcome(ctx) | ||
| } | ||
| // Do not add completion callbacks if activity already completed. | ||
| if outcome != nil { | ||
| return outcome, nil | ||
| } | ||
|
|
||
| return nil, a.addCompletionCallbacks(ctx, input.requestID, input.callbacks, input.maxCallbacks) | ||
| } |
Contributor
There was a problem hiding this comment.
I think we can simplify
Suggested change
| func (a *Activity) getOutcomeOrAddCallbacks( | |
| ctx chasm.MutableContext, input getOutcomeOrAddCallbacksInput, | |
| ) (*apiactivitypb.ActivityExecutionOutcome, error) { | |
| var outcome *apiactivitypb.ActivityExecutionOutcome | |
| if input.includeOutcome { | |
| outcome = a.outcome(ctx) | |
| } | |
| // Do not add completion callbacks if activity already completed. | |
| if outcome != nil { | |
| return outcome, nil | |
| } | |
| return nil, a.addCompletionCallbacks(ctx, input.requestID, input.callbacks, input.maxCallbacks) | |
| } | |
| func (a *Activity) getOutcomeOrAddCallbacks( | |
| ctx chasm.MutableContext, input getOutcomeOrAddCallbacksInput, | |
| ) (*apiactivitypb.ActivityExecutionOutcome, error) { | |
| if input.includeOutcome && a.LifecycleState(ctx).IsClosed() { | |
| return a.outcome(ctx), nil | |
| } | |
| return nil, a.addCompletionCallbacks(ctx, input.requestID, input.callbacks, input.maxCallbacks) | |
| } |
Simplified getOutcomeOrAddCallback by checking if activity state is closed, instead of presence of outcome. Refactor handling of AlreadyStartedErr in separate function. Return error from ReadComponent instead of AlreadyStartedErr if ReadComponent fails. Return immediately if error is present but is not AlreadyStartedErr.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed?
In StartActivityExecution if IncludeOutcome is set in the request and the
activity is already started, and the outcome is available, then instead of
returning AlreadyStarted error, return success with the outcome and runID
of the already started activity.
If the caller desires, it can set the IncludeOutcome in the request, and
the server will return the outcome when the reuse policy is set
to
AllowDuplicateFailedOnlyand the previous run succeeded,or when set to
RejectDuplicateand the previous run completed.Before adding the completion callbacks, do the same check, and avoid
adding callbacks on completed activity, as it will fail, but return success
with outcome of the completed activity. Refactor the check-and-add to
a new Activity function to allow unit test.
Why?
So that the outcome is included in response to StartActivityExecution
if the execution is already started, and the activity is already completed,
to avoid another query for the outcome.
When a caller's StartActivityExecution short-circuits to an existing run
with the same activity ID because of an ID reuse or conflict policy, the
caller often wants the outcome of the existing run, not just the identifier
or an error pointing at it. Retrieving the outcome in the response avoids
the caller to use a second RPC of DescribeActivityExecution to retrieve
a result that the server already has cached.
The activity outcome is embedded in a success response rather than
within an error, which otherwise would have happened without the
include_outcome request flag.
How did you test it?