Skip to content

Feat ts durable execution#3134

Merged
grutt merged 28 commits intofeat-durable-executionfrom
feat-durable-ts-sdk
Mar 6, 2026
Merged

Feat ts durable execution#3134
grutt merged 28 commits intofeat-durable-executionfrom
feat-durable-ts-sdk

Conversation

@grutt
Copy link
Copy Markdown
Contributor

@grutt grutt commented Mar 2, 2026

Description

Aligns typescript with the current python implementation

Type of change

  • New feature (non-breaking change which adds functionality)

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hatchet-docs Ready Ready Preview, Comment Mar 6, 2026 2:50pm

Request Review

@promptless-for-oss
Copy link
Copy Markdown

📝 Documentation updates detected!

Updated existing suggestions:


Tip: Enable auto-create PR in your Docs Collection to publish suggestions automatically 🤖

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds durable execution parity to the TypeScript SDK (matching the Python SDK), including durable event-log interactions, child spawning, memoization, replay/reset, and durable-task eviction support.

Changes:

  • Introduces a new durable-task gRPC streaming protocol in the TS durable listener and wires it into DurableContext (waitFor, spawnChild, memo).
  • Adds durable eviction support (policy + cache/manager) and worker integration to evict TTL/capacity-eligible waiting durable runs.
  • Adds/updates TypeScript E2E examples + tests for durable workflows, durable events, durable sleep, and eviction; plus some new unit tests for timeout resolution.

Reviewed changes

Copilot reviewed 43 out of 45 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
sdks/typescript/src/v1/task.ts Adds evictionPolicy option to durable task opts.
sdks/typescript/src/v1/parent-run-context-vars.ts Carries durable context through AsyncLocalStorage for child run() routing.
sdks/typescript/src/v1/index.ts Exports durable-related errors and eviction types/config.
sdks/typescript/src/v1/examples/e2e-worker.ts Registers many new durable/eviction example workflows for e2e.
sdks/typescript/src/v1/examples/durable_sleep/durable_sleep.e2e.ts New e2e test validating durable sleep behavior.
sdks/typescript/src/v1/examples/durable_eviction/workflow.ts New durable eviction example workflows (TTL/capacity/non-evictable).
sdks/typescript/src/v1/examples/durable_eviction/durable_eviction.e2e.ts New e2e suite covering eviction + restore flows.
sdks/typescript/src/v1/examples/durable_event/workflow.ts Makes durable event waits awaited; factors event key constant.
sdks/typescript/src/v1/examples/durable_event/durable_event.e2e.ts New e2e suite for durable event wait (with/without filter).
sdks/typescript/src/v1/examples/durable/workflow.ts Expands durable examples: spawn child, memo, non-determinism, replay reset, spawn DAG.
sdks/typescript/src/v1/examples/durable/durable.e2e.ts Expands durable e2e coverage for the new durable behaviors.
sdks/typescript/src/v1/examples/durable-event/workflow.ts Updates hyphenated durable-event example to await waits.
sdks/typescript/src/v1/declaration.ts Adds durable child-run routing when invoked under a durable parent context.
sdks/typescript/src/v1/conditions/transformer.ts Normalizes sleep durations via durationToString when encoding PB conditions.
sdks/typescript/src/v1/conditions/sleep-condition.ts Normalizes readable keys using durationToString.
sdks/typescript/src/v1/conditions/contitions.test.ts Updates expected render output to use normalized duration strings.
sdks/typescript/src/v1/client/worker/worker-timeouts.test.ts New unit tests for timeout resolution helpers.
sdks/typescript/src/v1/client/worker/worker-internal.ts Integrates durable execution: durable listener startup, eviction manager, durable contexts, timeout normalization, improved cancellation semantics.
sdks/typescript/src/v1/client/worker/worker-cancel-supervision.test.ts Updates cancellation supervision test scaffolding for new cleanup path.
sdks/typescript/src/v1/client/worker/eviction/index.ts New export barrel for eviction subsystem.
sdks/typescript/src/v1/client/worker/eviction/eviction-policy.ts New EvictionPolicy type + default durable eviction policy.
sdks/typescript/src/v1/client/worker/eviction/eviction-manager.ts New eviction loop + shutdown eviction.
sdks/typescript/src/v1/client/worker/eviction/eviction-cache.ts New eviction candidate selection logic (TTL/capacity).
sdks/typescript/src/v1/client/worker/context.ts DurableContext now uses durable event-log streaming; adds spawnChild + memo; adds eviction wait-marking; normalizes refreshTimeout durations.
sdks/typescript/src/v1/client/features/runs.ts Adds restoreTask + resetDurableTask helpers.
sdks/typescript/src/v1/client/duration.ts Extends Duration to support object-form durations and adds duration normalization helpers.
sdks/typescript/src/v1/client/client.ts Updates DurableListenerClient construction signature.
sdks/typescript/src/util/sleep.ts Extends sleep helper to accept Duration (string/object) as well as milliseconds.
sdks/typescript/src/util/errors/task-run-terminated-error.ts New shared error type for cancellation/eviction termination.
sdks/typescript/src/util/errors/non-determinism-error.ts New error type for durable non-determinism signaling.
sdks/typescript/src/protoc/workflows/workflows.ts Deduplicates TriggerWorkflowRequest by importing shared trigger proto.
sdks/typescript/src/protoc/v1/workflows.ts Adds EVICTED run status and durable fork RPC message types + admin service method.
sdks/typescript/src/protoc/v1/shared/trigger.ts New shared TriggerWorkflowRequest proto module.
sdks/typescript/src/protoc/v1/dispatcher.ts Adds durable-task streaming protocol messages/RPC and imports shared TriggerWorkflowRequest.
sdks/typescript/src/protoc/dispatcher/dispatcher.ts Extends AssignedAction with durable invocation count; adds restore-evicted-task RPC/types.
sdks/typescript/src/legacy/step.ts Normalizes refreshTimeout duration serialization for legacy context.
sdks/typescript/src/legacy/legacy-client.ts Updates DurableListenerClient construction signature.
sdks/typescript/src/clients/rest/generated/data-contracts.ts Adds EVICTED statuses + durable restore/fork request/response types.
sdks/typescript/src/clients/rest/generated/Api.ts Adds REST endpoints for task restore and durable task fork.
sdks/typescript/src/clients/listeners/durable-listener/durable-listener-client.ts Major rewrite: durable task event-log streaming client + legacy backward compatibility.
examples/typescript/e2e-worker.ts Registers the expanded durable/eviction examples in root examples.
examples/typescript/durable_eviction/workflow.ts New root example workflow for durable eviction.
examples/typescript/durable_event/workflow.ts Updates root durable_event example to await waits + reuse event key constant.
examples/typescript/durable/workflow.ts Expands root durable workflow examples similarly to SDK examples.
examples/typescript/durable-event/workflow.ts Updates root hyphenated durable-event example to await waits.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread sdks/typescript/src/v1/client/worker/eviction/eviction-cache.ts
Comment thread sdks/typescript/src/v1/client/worker/worker-internal.ts
Comment thread sdks/typescript/src/v1/task.ts
Comment thread sdks/typescript/src/v1/client/features/runs.ts
Comment thread sdks/typescript/src/v1/client/duration.ts Outdated
Copy link
Copy Markdown
Contributor

@mrkaye97 mrkaye97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some comments but looks basically good!

type PendingCallbackKey = `${TaskExternalId}:${InvocationCount}:${BranchId}:${NodeId}`;
type PendingEvictionAckKey = `${TaskExternalId}:${InvocationCount}`;

function ackKey(taskExtId: string, invocationCount: number): PendingEventAckKey {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the types here be taskExtId: TaskExternalId, invocationCount: InvocationCount?

Comment on lines +102 to +105
taskExtId: string,
invocationCount: number,
branchId: number,
nodeId: number
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here - I should probably do this in Python too if I haven't

Comment thread sdks/typescript/src/legacy/step.ts
Comment thread sdks/typescript/src/v1/client/features/runs.ts Outdated
* @param options - Options for spawning the child workflow.
* @returns The result of the child workflow.
*/
async spawnChild<Q extends JsonObject, P extends JsonObject>(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in python this is intended to be private (and only called from e.g. workflow.run)

* @returns The result of the child workflow.
*/
async spawnChild<Q extends JsonObject, P extends JsonObject>(
workflow: string | WorkflowV1<Q, P> | TaskWorkflowDeclaration<Q, P>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we've done this some other places, but I reeeaaaalllyyyyy dislike this overload, the whole goal of a lot of the wrapper code in Python is to not be allowing people to do things that rely on e.g. the workflow name, and also the typing is so much worse if we allow this instead of only allowing a Workflow object (in Python we have BaseWorkflow so we don't need the union type either)

* @param args - The arguments to pass to the function. These form the memoization key.
* @returns The memoized value, either from durable storage or freshly computed.
*/
async memo<R>(fn: (...args: any[]) => Promise<R>, ...args: any[]): Promise<R> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do this without any?

@promptless-for-oss
Copy link
Copy Markdown

📝 Documentation updates detected!

Updated existing suggestion: Document durable execution with eviction policies, NonDeterminismError, and best practices


Tip: Worried about broken links? Ask Promptless to find and fix them automatically 🔗

@grutt grutt force-pushed the feat-durable-ts-sdk branch from 615340a to 57e0ff9 Compare March 6, 2026 00:28
Comment thread sdks/typescript/src/v1/declaration.ts Outdated
if (durableCtx) {
if (Array.isArray(input)) {
return durableCtx.spawnChildren(
input.map((inp) => ({ workflow: this as any, input: inp as any, options }))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clean up types

@grutt grutt merged commit f177f11 into feat-durable-execution Mar 6, 2026
51 of 52 checks passed
@grutt grutt deleted the feat-durable-ts-sdk branch March 6, 2026 18:00
@promptless-for-oss
Copy link
Copy Markdown

📝 Documentation updates detected!

Updated existing suggestions:


Tip: Tell your friends working on non-commercial open-source projects to apply for free Promptless access at promptless.ai/oss ❤️

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