feat(activity): notify Activities when the Worker starts shutting down - #2264
Open
rohitsudhakar1 wants to merge 1 commit into
Open
feat(activity): notify Activities when the Worker starts shutting down#2264rohitsudhakar1 wants to merge 1 commit into
rohitsudhakar1 wants to merge 1 commit into
Conversation
|
|
Other SDKs let an Activity know that its Worker has begun shutting down, before expiration of the shutdown grace period: Go has GetWorkerStopChannel(), Python has wait_for_worker_shutdown() and .NET has WorkerShutdownToken. The TypeScript SDK had no equivalent, so a long running Activity only learned about shutdown once the grace period expired and it got abruptly cancelled, leaving no opportunity to checkpoint its progress and return. Add `Context.workerShuttingDown` (a Promise<never>) and `Context.workerShuttingDownSignal` (an AbortSignal), mirroring the existing `cancelled` / `cancellationSignal` pair, along with matching top level exports from `@temporalio/activity`. The Worker owns a single AbortController, aborted from the `state` setter as soon as the Worker leaves the RUNNING state, so that every shutdown path is covered, including error driven ones. Each Activity derives its own controller from that shared signal, so that user code may register listeners without accumulating them on the Worker's signal. A shutdown notification is deliberately not a cancellation: the Activity's cancellation signal and cancellation details are left untouched, and the Activity remains free to complete normally. `MockActivityEnvironment.notifyWorkerShuttingDown()` exposes the notification so that Activities can be tested against it. Closes temporalio#1739
rohitsudhakar1
force-pushed
the
feat-1739-worker-shutting-down
branch
from
July 28, 2026 02:01
60e3305 to
319abeb
Compare
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.
Closes #1739.
What #1739 asked for
workerShuttingDown: Promise<never>andworkerShuttingDownSignal: AbortSignalon the ActivityContext, mirroring how cancellation is handled, plus matching top-level exports fromactivity/index.ts.What this implements
Context.workerShuttingDown— aPromise<never>that rejects withCancelledFailure('WORKER_SHUTDOWN')as soon as the Worker initiates shutdown, andContext.workerShuttingDownSignal— the correspondingAbortSignal. These mirror the existingcancelled/cancellationSignalpair.workerShuttingDown()andworkerShuttingDownSignal()from@temporalio/activity, as shortcuts forContext.current().…, consistent with the existingcancelled()/cancellationSignal()helpers.AbortController, aborted from thestatesetter as soon as the Worker leavesRUNNING, so every shutdown path is covered — including error-driven ones — rather than just the happy-pathshutdown()call. Each Activity derives its own controller from that shared signal, so user code can register listeners without accumulating them on the Worker's signal for the Worker's whole lifetime.cancellationSignalandcancellationDetailsare left untouched and the Activity remains free to complete normally. Unlike cancellation, an Activity also does not need toheartbeat()to learn about shutdown.MockActivityEnvironment.notifyWorkerShuttingDown(), so Activities that use the new API are testable without standing up a real Worker. This wasn't in the issue text, but the API is untestable in user code without it.Both
Contextmembers are documented as@experimental.Tests
Four new tests in
packages/testing/src/__tests__/test-mockactivityenv.ts:workerShuttingDownand abortsworkerShuttingDownSignal, and the Activity still completes normally afterwards;cancellationSignalstays un-aborted,cancellationDetails()staysundefined, andsleep()still works;Promise.race([work, workerShuttingDown()])bail-out pattern;These provably fail without the change: reverting only the four implementation files and rebuilding fails compilation on every new API reference (
TS2339: Property 'workerShuttingDown' does not exist…), so the tests cannot pass againstmain. With the change, the fulltest-mockactivityenvsuite passes (8/8).eslint,prettier --checkandlint:pruneare all clean.Cross-SDK parity
This brings TypeScript in line with the other SDKs, which all expose worker-shutdown notification distinctly from cancellation:
activity.GetWorkerStopChannelactivity.wait_for_worker_shutdownActivityExecutionContext.WorkerShutdownTokenThe
Promise/AbortSignalpairing follows the shape #1739 specified and matches how this SDK already surfaces cancellation, rather than importing another SDK's idiom.Happy to adjust naming, the
@experimentalmarkers, or the choice to fire on any non-RUNNINGstate transition if maintainers would prefer it scoped only to explicitshutdown().