Skip to content

Dispatch cancel command for standalone activities - #10218

Open
rkannan82 wants to merge 30 commits into
mainfrom
kannan/standalone-activity-cancel-commands
Open

Dispatch cancel command for standalone activities#10218
rkannan82 wants to merge 30 commits into
mainfrom
kannan/standalone-activity-cancel-commands

Conversation

@rkannan82

@rkannan82 rkannan82 commented May 11, 2026

Copy link
Copy Markdown
Contributor

What

Send activity cancellation commands for standalone activities to the worker. When a standalone activity is cancelled or terminated while running on a worker, the server proactively notifies the worker via a cancel command through the Nexus worker commands control queue.

Key changes:

  • Record the ComponentRef from matching's RecordActivityTaskStartedRequest in the attempt state. This is the exact ref matching used to build the poll token, ensuring the cancel command token matches.
  • Define CancelCommandDispatchTask as a CHASM side-effect task, and dispatch it using the existing workercommands.Dispatcher API.
  • Use TaskInvocation.Attempt to enforce max retry attempts in Validate, preventing infinite retries on standby clusters.
  • Standalone activity tokens use ComponentRef as the sole routing identifier — WorkflowId/RunId are left empty since they don't apply.

Why

Without proactive notification, cancelled standalone activities would only stop when they use activity heartbeats, or wait till they time out.

How did you test it?

  • Unit tests: state machine transitions (cancel requested, terminated) schedule the dispatch task
  • Functional tests: cancel command dispatch via the Nexus control queue, cancel API with various scenarios

🤖 Generated with Claude Code

@rkannan82
rkannan82 force-pushed the kannan/standalone-activity-cancel-commands branch from 77e0a54 to d68c034 Compare May 11, 2026 19:26
@rkannan82
rkannan82 changed the base branch from main to kannan/move-dispatch-response-to-error May 11, 2026 19:26
@rkannan82
rkannan82 force-pushed the kannan/standalone-activity-cancel-commands branch from 7b46553 to 47b1c94 Compare June 10, 2026 23:28
@rkannan82
rkannan82 changed the base branch from kannan/move-dispatch-response-to-error to kannan/extract-worker-commands-dispatch June 11, 2026 17:11
rkannan82 added a commit that referenced this pull request Jun 24, 2026
## What

Move `dispatchResponseToError` and `startOperationResponseToError` from
`service/history` to `common/nexus` as exported functions.

## Why

To reuse in standalone activities. See
[PR](#10218)

## How did you test it?

Existing unit tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 changed the base branch from kannan/extract-worker-commands-dispatch to main June 24, 2026 19:26
stephanos pushed a commit that referenced this pull request Jun 25, 2026
## What

Move `dispatchResponseToError` and `startOperationResponseToError` from
`service/history` to `common/nexus` as exported functions.

## Why

To reuse in standalone activities. See
[PR](#10218)

## How did you test it?

Existing unit tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
rkannan82 and others added 3 commits June 25, 2026 17:48
Move the entire workerCommandsTaskDispatcher from service/history to
common/workercommands so it can be reused by CHASM standalone activities
(which cannot import service/history due to circular dependency).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 force-pushed the kannan/standalone-activity-cancel-commands branch from a87bac3 to f5221d3 Compare June 26, 2026 01:25
@rkannan82
rkannan82 changed the base branch from main to kannan/chasm-activity-task-token June 26, 2026 01:25
When a standalone activity is cancelled or terminated while running on a
worker, proactively notify the worker via a cancel command dispatched
through the Nexus worker commands control queue. This is best-effort —
the activity will eventually time out if the worker doesn't respond.

Key changes:
- Add CancelCommandDispatchTask side-effect task and handler
- Store started-time ComponentRef in ActivityAttemptState so cancel
  tokens are byte-identical to poll tokens (SDK does exact byte match)
- Set Execution field in AddActivityTaskRequest for correct WorkflowId/RunId
- Add NewStandaloneActivityTaskToken to common/tasktoken
- Wire cancel dispatch on cancel-requested and terminate transitions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 force-pushed the kannan/standalone-activity-cancel-commands branch from f5221d3 to 77d9d48 Compare June 26, 2026 02:01
The functional test TestDispatchCancelCommandToWorker already validates
that the cancel command token matches the poll token end-to-end.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 marked this pull request as ready for review June 26, 2026 15:06
@rkannan82
rkannan82 requested review from a team as code owners June 26, 2026 15:06
@rkannan82
rkannan82 requested a review from yycptt June 26, 2026 15:06
rkannan82 and others added 2 commits June 26, 2026 11:57
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 force-pushed the kannan/standalone-activity-cancel-commands branch from 6f8f5ff to c9c7da3 Compare June 26, 2026 19:05
Comment thread chasm/lib/activity/worker_command_task_handlers.go Outdated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 requested a review from dandavison June 26, 2026 20:04
rkannan82 and others added 3 commits July 6, 2026 22:21
…l-commands' into kannan/standalone-activity-cancel-commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Unpack fx.In options into individual handler struct fields, matching the
callback invocationTaskHandler pattern. Simplify NewStandaloneActivityTaskToken
to take a single activityID since workflowID and activityID are always
identical for standalone activities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 requested review from rodrigozhou and yycptt July 7, 2026 23:19
rkannan82 and others added 2 commits July 8, 2026 15:46
Capture the ComponentRef from RecordActivityTaskStartedRequest instead
of ctx.Ref(a). This is the exact ref matching used to build the poll
token, so the cancel command token is guaranteed to match even if the
component is mutated between dispatch and start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the cancel_command_dispatched flag and associated logic. Standby
handling will be addressed via a new CHASM abstraction instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
trangnguyenkp pushed a commit to trangnguyenkp/temporal that referenced this pull request Jul 9, 2026
## What

Move `dispatchResponseToError` and `startOperationResponseToError` from
`service/history` to `common/nexus` as exported functions.

## Why

To reuse in standalone activities. See
[PR](temporalio#10218)

## How did you test it?

Existing unit tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
trangnguyenkp pushed a commit to trangnguyenkp/temporal that referenced this pull request Jul 9, 2026
…emporalio#10849)

## What

Moves `worker_commands_task_dispatcher.go` from `service/history` to
`common/workercommands/dispatcher.go` and exports its types. The call
site in `outbound_queue_active_task_executor.go` is updated to use the
new import path.

## Why

To reuse this in [PR](temporalio#10218)
that sends cancel commands for standalone activities.

## How did you test it?

- Existing unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
rkannan82 and others added 3 commits July 9, 2026 10:25
Now that CHASM exposes attempt count via TaskAttributes, use it to:
- Drop the cancel command dispatch task after MaxTaskAttempts in Validate
- Pass the real attempt count to the dispatcher instead of hardcoded 1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use TaskInvocation (not TaskAttributes) in Validate, since Attempt is
only available there. Keep dispatcher call with attempt=1 since max
attempts are enforced in Validate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rkannan82 and others added 7 commits July 13, 2026 16:42
Standalone activities route responses via ComponentRef, not WorkflowId
or RunId. Remove the Execution field from AddActivityTaskRequest and
simplify NewStandaloneActivityTaskToken to pass empty strings, matching
what matching produces in the poll token.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standalone activities don't have a parent workflow. Remove the Execution
field from AddActivityTaskRequest and leave WorkflowId/RunId empty in
NewStandaloneActivityTaskToken. Matching gets ActivityId from the
RecordActivityTaskStartedResponse, not from AddActivityTaskRequest, so
the poll and cancel command tokens remain consistent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Unit tests for cancelCommandDispatchTaskHandler.Validate: status
  checks and max attempt enforcement
- TransitionStarted test: verify ComponentRef and WorkerControlTaskQueue
  are captured from RecordActivityTaskStartedRequest
- E2e test: terminate dispatches cancel command to worker control queue

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l-commands' into kannan/standalone-activity-cancel-commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rkannan82
rkannan82 force-pushed the kannan/standalone-activity-cancel-commands branch from 950ab6d to aee246f Compare July 14, 2026 22:02
spkane31 pushed a commit that referenced this pull request Jul 15, 2026
## What

Move `dispatchResponseToError` and `startOperationResponseToError` from
`service/history` to `common/nexus` as exported functions.

## Why

To reuse in standalone activities. See
[PR](#10218)

## How did you test it?

Existing unit tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
spkane31 pushed a commit that referenced this pull request Jul 15, 2026
…10849)

## What

Moves `worker_commands_task_dispatcher.go` from `service/history` to
`common/workercommands/dispatcher.go` and exports its types. The call
site in `outbound_queue_active_task_executor.go` is updated to use the
new import path.

## Why

To reuse this in [PR](#10218)
that sends cancel commands for standalone activities.

## How did you test it?

- Existing unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
rkannan82 and others added 4 commits July 15, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants