workflow 5.0.0-beta.37 → 5.0.0-beta.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -16
- package/dist/api.d.ts +1 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +1 -1
- package/docs/api-reference/workflow-api/resume-hook.mdx +1 -1
- package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +9 -3
- package/docs/changelog/index.mdx +2 -1
- package/docs/changelog/meta.json +1 -0
- package/docs/changelog/resilient-resume.mdx +22 -0
- package/docs/configuration/runtime-tuning.mdx +37 -2
- package/docs/configuration/worlds.mdx +15 -3
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -28,22 +28,6 @@ The Workflow SDK community can be found on [GitHub Discussions](https://github.c
|
|
|
28
28
|
|
|
29
29
|
Contributions to Workflow SDK are welcome and highly appreciated. Please use GitHub [issues](https://github.com/vercel/workflow/issues) and [discussions](https://github.com/vercel/workflow/discussions) to collaborate with the team and wider community.
|
|
30
30
|
|
|
31
|
-
## Author list
|
|
32
|
-
|
|
33
|
-
Workflow SDK was built by engineers at [Vercel](https://vercel.com) and the [Open Source Community](https://github.com/vercel/workflow/graphs/contributors).
|
|
34
|
-
|
|
35
|
-
The initial core contributing engineers are:
|
|
36
|
-
|
|
37
|
-
- Adrian Lam ([@adriandlam](https://github.com/adriandlam))
|
|
38
|
-
- Dillon Mulroy ([@dmmulroy](https://github.com/dmmulroy))
|
|
39
|
-
- Gal Schlezinger ([@Schniz](https://github.com/Schniz))
|
|
40
|
-
- JJ Kasper ([@ijjk](https://github.com/ijjk))
|
|
41
|
-
- Nathan Rajlich ([@TooTallNate](https://github.com/TooTallNate))
|
|
42
|
-
- Peter Wielander ([@VaguelySerious](https://github.com/VaguelySerious))
|
|
43
|
-
- Pranay Prakash ([@pranaygp](https://github.com/pranaygp))
|
|
44
|
-
|
|
45
|
-
The Workflow SDK logo was designed by Cecilio Ruiz [@ceciliorz](https://x.com/ceciliorz)
|
|
46
|
-
|
|
47
31
|
---
|
|
48
32
|
|
|
49
33
|
## Security
|
package/dist/api.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '@workflow/core/runtime/world-init';
|
|
2
2
|
export type { CancelRunOptions, Event, StopSleepOptions, StopSleepResult, WorkflowRun, } from '@workflow/core/runtime';
|
|
3
|
-
export { getHookByToken, resumeHook, resumeWebhook, } from '@workflow/core/runtime/resume-hook';
|
|
3
|
+
export { getHookByToken, type ResumedHook, resumeHook, resumeWebhook, } from '@workflow/core/runtime/resume-hook';
|
|
4
4
|
export { getRun, Run, type WorkflowReadableStream, type WorkflowReadableStreamOptions, } from '@workflow/core/runtime/run';
|
|
5
5
|
export { type StartOptions, start, } from '@workflow/core/runtime/start';
|
|
6
6
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAOA,OAAO,mCAAmC,CAAC;AAE3C,YAAY,EACV,gBAAgB,EAChB,KAAK,EACL,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,cAAc,EACd,UAAU,EACV,aAAa,GACd,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,MAAM,EACN,GAAG,EACH,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,GACnC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,GACN,MAAM,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAOA,OAAO,mCAAmC,CAAC;AAE3C,YAAY,EACV,gBAAgB,EAChB,KAAK,EACL,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,UAAU,EACV,aAAa,GACd,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,MAAM,EACN,GAAG,EACH,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,GACnC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,GACN,MAAM,8BAA8B,CAAC"}
|
package/dist/api.js
CHANGED
|
@@ -9,4 +9,4 @@ import '@workflow/core/runtime/world-init';
|
|
|
9
9
|
export { getHookByToken, resumeHook, resumeWebhook, } from '@workflow/core/runtime/resume-hook';
|
|
10
10
|
export { getRun, Run, } from '@workflow/core/runtime/run';
|
|
11
11
|
export { start, } from '@workflow/core/runtime/start';
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxRUFBcUU7QUFDckUseUVBQXlFO0FBQ3pFLDJFQUEyRTtBQUMzRSw0RUFBNEU7QUFDNUUsNkVBQTZFO0FBQzdFLG1CQUFtQjtBQUNuQix5RUFBeUU7QUFDekUsT0FBTyxtQ0FBbUMsQ0FBQztBQVMzQyxPQUFPLEVBQ0wsY0FBYyxFQUVkLFVBQVUsRUFDVixhQUFhLEdBQ2QsTUFBTSxvQ0FBb0MsQ0FBQztBQUM1QyxPQUFPLEVBQ0wsTUFBTSxFQUNOLEdBQUcsR0FHSixNQUFNLDRCQUE0QixDQUFDO0FBQ3BDLE9BQU8sRUFFTCxLQUFLLEdBQ04sTUFBTSw4QkFBOEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFNpZGUtZWZmZWN0IGltcG9ydDogZW5zdXJlIGB3b3JsZC50c2AgaXMgbG9hZGVkIHNvIGl0cyBtb2R1bGUtbG9hZFxuLy8gYGdsb2JhbFRoaXNbR2V0V29ybGRGbktleV0gPz89IGdldFdvcmxkYCByZWdpc3RyYXRpb24gZmlyZXMgYmVmb3JlIGFueVxuLy8gaG9zdCByb3V0ZSByZWFjaGVzIGBnZXRXb3JsZExhenkoKWAuIFdpdGhvdXQgdGhpcywgd2VicGFjay90dXJib3BhY2sgY2FuXG4vLyB0cmVlLXNoYWtlIGB3b3JsZC50c2Agb3V0IG9mIHJvdXRlcyB0aGF0IG9ubHkgdXNlIGBzdGFydGAuIFJlc29sdmVkIHRvIGFuXG4vLyBlbXB0eSBzdHViIHZpYSB0aGUgYHdvcmtmbG93YCBleHBvcnQgY29uZGl0aW9uIGluIFZNL3N0ZXAgYnVuZGxlcywgc28gdGhpc1xuLy8gc3RheXMgaG9zdC1vbmx5LlxuLy8gU2VlIGBAd29ya2Zsb3cvY29yZS9zcmMvcnVudGltZS93b3JsZC1pbml0LnRzYCBmb3IgdGhlIGZ1bGwgcmF0aW9uYWxlLlxuaW1wb3J0ICdAd29ya2Zsb3cvY29yZS9ydW50aW1lL3dvcmxkLWluaXQnO1xuXG5leHBvcnQgdHlwZSB7XG4gIENhbmNlbFJ1bk9wdGlvbnMsXG4gIEV2ZW50LFxuICBTdG9wU2xlZXBPcHRpb25zLFxuICBTdG9wU2xlZXBSZXN1bHQsXG4gIFdvcmtmbG93UnVuLFxufSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lJztcbmV4cG9ydCB7XG4gIGdldEhvb2tCeVRva2VuLFxuICB0eXBlIFJlc3VtZWRIb29rLFxuICByZXN1bWVIb29rLFxuICByZXN1bWVXZWJob29rLFxufSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lL3Jlc3VtZS1ob29rJztcbmV4cG9ydCB7XG4gIGdldFJ1bixcbiAgUnVuLFxuICB0eXBlIFdvcmtmbG93UmVhZGFibGVTdHJlYW0sXG4gIHR5cGUgV29ya2Zsb3dSZWFkYWJsZVN0cmVhbU9wdGlvbnMsXG59IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUvcnVuJztcbmV4cG9ydCB7XG4gIHR5cGUgU3RhcnRPcHRpb25zLFxuICBzdGFydCxcbn0gZnJvbSAnQHdvcmtmbG93L2NvcmUvcnVudGltZS9zdGFydCc7XG4iXX0=
|
|
@@ -50,7 +50,7 @@ showSections={["parameters"]}
|
|
|
50
50
|
|
|
51
51
|
### Returns
|
|
52
52
|
|
|
53
|
-
Returns a `Promise<
|
|
53
|
+
Returns a `Promise<ResumedHook>` — a `Hook` extended with an optional `resilientResume` flag. Resolving means the resume was accepted and the workflow will continue, whether the `hook_received` event was written directly or, on the parallel fast path, delivered through the workflow queue for the runtime to materialize (see the [lazy hook resume changelog](/docs/changelog/resilient-resume)). `resilientResume` is `true` only when the direct event write failed transiently and the resume was recovered through the queue; on the happy path it is absent. The resolved hook:
|
|
54
54
|
|
|
55
55
|
<TSDoc
|
|
56
56
|
definition={`
|
|
@@ -8,14 +8,18 @@ related:
|
|
|
8
8
|
- /docs/api-reference/workflow-errors/entity-conflict-error
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
`PreconditionFailedError` is thrown by world implementations when an event creation is rejected because the client's event-log snapshot is stale — a newer out-of-band event (such as a received hook or a completed step) was recorded after the snapshot the client replayed from. It corresponds to HTTP 412 Precondition Failed semantics.
|
|
11
|
+
`PreconditionFailedError` is thrown by world implementations when an event creation is rejected because the client's event-log snapshot is stale — either a newer out-of-band event (such as a received hook or a completed step) was recorded after the snapshot the client replayed from, or the snapshot is missing an event recorded at or before it. It corresponds to HTTP 412 Precondition Failed semantics.
|
|
12
12
|
|
|
13
|
-
This only occurs
|
|
13
|
+
This only occurs while the optimistic-concurrency guard is enabled (`WORKFLOW_PRECONDITION_GUARD`, on by default — see [Runtime Tuning](/docs/configuration/runtime-tuning)); event creations that carry no snapshot are never rejected with this error.
|
|
14
|
+
|
|
15
|
+
A world rejects only on evidence and accepts the creation whenever it cannot decide, so this error always means the snapshot really was stale — but not receiving it does not prove the snapshot was current.
|
|
14
16
|
|
|
15
17
|
<Callout>
|
|
16
|
-
The Workflow runtime handles this error automatically: it
|
|
18
|
+
The Workflow runtime handles this error automatically: it restarts the replay in the same invocation from a corrected event log, and re-invokes the run for a fresh replay only once its in-process restart budget is spent. It never retries the rejected creation as-is, because a replay working from a corrected log derives different events. You will only encounter it when interacting with world storage APIs directly.
|
|
17
19
|
</Callout>
|
|
18
20
|
|
|
21
|
+
A world may attach the events the client was missing to the rejection as `details`, which lets the runtime restart without re-reading the event log. Doing so is optional, and the runtime falls back to a full reload when the details are absent or unusable.
|
|
22
|
+
|
|
19
23
|
```typescript lineNumbers
|
|
20
24
|
import { PreconditionFailedError } from "workflow/errors"
|
|
21
25
|
declare const world: { events: { create(...args: any[]): Promise<any> } }; // @setup
|
|
@@ -40,6 +44,8 @@ definition={`
|
|
|
40
44
|
interface PreconditionFailedError {
|
|
41
45
|
/** Delay in seconds before the operation should be retried. Present when the server sends a Retry-After header. */
|
|
42
46
|
retryAfter?: number;
|
|
47
|
+
/** Optional rejection payload. A world may put the events the client was missing here, as \`{ events, cursor }\`, so the runtime can restart its replay without re-reading the event log. */
|
|
48
|
+
details?: unknown;
|
|
43
49
|
/** The error message. */
|
|
44
50
|
message: string;
|
|
45
51
|
}
|
package/docs/changelog/index.mdx
CHANGED
|
@@ -12,5 +12,6 @@ Stay up to date with the latest changes to Workflow SDK.
|
|
|
12
12
|
|
|
13
13
|
## 2026
|
|
14
14
|
|
|
15
|
-
- [
|
|
15
|
+
- [Resilient hook resume](/docs/changelog/resilient-resume) — July 2026
|
|
16
|
+
- [Eager processing of steps and incremental event replay](/docs/changelog/eager-processing) — March 2026
|
|
16
17
|
- Serializable AbortController and AbortSignal — March 12, 2026
|
package/docs/changelog/meta.json
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Resilient hook resume
|
|
3
|
+
description: resumeHook() now tolerates transient event storage failures, as long as the queue is healthy, instead of failing the resume.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Resilient `resumeHook()`
|
|
7
|
+
|
|
8
|
+
## Motivation
|
|
9
|
+
|
|
10
|
+
`resumeHook()` used to write the `hook_received` event and dispatch the workflow queue message strictly one after the other, so every resume paid two sequential round trips and a transient event-storage failure failed the whole resume even when the queue was healthy. This change runs both writes **concurrently** — cutting a round trip off resume latency — and, on the same path, brings `resumeHook()` to parity with [resilient `start()`](/docs/changelog/resilient-start): a transient event-write failure no longer fails the resume when the payload can still be delivered through the queue.
|
|
11
|
+
|
|
12
|
+
## Design
|
|
13
|
+
|
|
14
|
+
- On the fast path, `resumeHook()` writes the `hook_received` event and dispatches the workflow queue message **concurrently** (`Promise.allSettled`). The queue message carries a `hookInput` payload — the dehydrated hook payload plus a client-minted `resumeId` idempotency key, the hook token, and a payload digest.
|
|
15
|
+
- A `(runId, resumeId)` dedup constraint keeps the two writers converging on **exactly one** `hook_received` event: whichever lands first wins, and the other is resolved server-side as success rather than a duplicate. The queue consumer idempotently re-ensures the event from `hookInput` before replay, so the resume is guaranteed even if the direct write never commits.
|
|
16
|
+
- Replay also deduplicates: `hook_received` events sharing a `resumeId` belong to the same resume attempt, and only the first in the event log is delivered to workflow code. Even if a redelivery materializes the event twice, the payload reaches the workflow exactly once.
|
|
17
|
+
- **Queue dispatch failure is fatal** — the run was not re-triggered, so no consumer will re-ensure the event, and `resumeHook()` throws. A transient event-write failure (429/5xx, a transport error, or an expected `(runId, resumeId)` conflict with the consumer's own re-ensure) is swallowed because the queue delivery still guarantees the resume; a terminal run surfaces as `HookNotFoundError`, and any other event-write error is rethrown.
|
|
18
|
+
- `resumeHook()` returns `ResumedHook` (exported from `workflow/api`), which extends `Hook` with an optional `resilientResume` flag. The flag is `true` only when the direct write failed transiently and the resume was recovered through the queue; on the happy path and the sequential fallback it is absent.
|
|
19
|
+
|
|
20
|
+
## Compatibility
|
|
21
|
+
|
|
22
|
+
The parallel fast path is gated per resume: it activates only when both the target run's queue consumer and the live backend independently attest dedup support (re-checked on every resume, so rollout and rollback both degrade safely). Otherwise — for oversized payloads, legacy runs, or with `WORKFLOW_DISABLE_LAZY_HOOK_RESUME=1` — `resumeHook()` falls back to the original sequential write-then-dispatch path. Because runs keep executing on the deployment they were created on, a resume targeting a run from an older deployment simply uses the sequential path.
|
|
@@ -38,16 +38,43 @@ For example, a workflow can run a 10-minute inline step even with `WORKFLOW_REPL
|
|
|
38
38
|
- Default: `3`
|
|
39
39
|
- Recovery replays before replay divergence is recorded as corruption.
|
|
40
40
|
|
|
41
|
+
### `WORKFLOW_DISABLE_LAZY_HOOK_RESUME`
|
|
42
|
+
|
|
43
|
+
- Default: enabled (lazy hook resume on)
|
|
44
|
+
- Resuming a hook persists the `hook_received` event and publishes the workflow invocation concurrently, cutting a round trip off resume latency. On this parallel path the queue message also carries the payload, so a transient event-write failure still resumes the run — the queue consumer re-ensures the `hook_received` event before replay. A backend `(runId, resumeId)` constraint keeps the two writers converging on exactly one event.
|
|
45
|
+
- The runtime falls back to the sequential path automatically when the consumer or backend does not attest dedup support (or the payload is too large to inline on the queue message). On the sequential path the event is written *before* dispatch and its failure fails the resume — the fallback trades that resilience away to stay safe when dedup is not enforced, it does not preserve it.
|
|
46
|
+
- Set `1` to force the sequential path as a kill switch. The chosen strategy is reported on the resume span as `workflow.hook.resume_strategy`.
|
|
47
|
+
|
|
41
48
|
### `WORKFLOW_PRECONDITION_GUARD`
|
|
42
49
|
|
|
43
50
|
- Default: enabled
|
|
44
|
-
- An optimistic-concurrency guard for event creation: replay-context event creations
|
|
45
|
-
- On rejection the runtime
|
|
51
|
+
- An optimistic-concurrency guard for event creation: replay-context event creations describe the snapshot they replayed from — its latest event timestamp (`stateUpdatedAt`), the number of events it contains (`stateEventCount`), and its event-log cursor (`stateCursor`) — and a backend that supports the guard rejects a creation with 412 ([`PreconditionFailedError`](/docs/api-reference/workflow-errors/precondition-failed-error)) when a newer out-of-band event (a received hook or a completed step) was recorded after that snapshot, or when the snapshot is missing an event recorded at or before it.
|
|
52
|
+
- On rejection the runtime restarts the replay in the same invocation from a corrected event log, and falls back to a re-invocation with a fresh replay once the restart budget is spent. The rejected write is never retried as-is: a replay working from a corrected log derives different events, so only a fresh replay may write again.
|
|
46
53
|
- When enabled — and the World declares that it enforces the guard (`capabilities.preconditionGuard`; the Vercel World does) — the runtime also keeps the per-step event-log delta optimization (consuming the delta returned by a step's terminal write instead of issuing an extra `events.list` per step) active while the run has an open hook. Without an enforced guard, an open hook disables it.
|
|
47
54
|
- While a hook is open on a guard-enforcing deployment, inline steps take the await-then-run path even when optimistic inline start is enabled: the step's `step_started` claim carries the snapshot and is awaited before the body runs, so a claim the backend rejects as stale never executes user code.
|
|
48
55
|
- Backends that do not support the guard ignore the snapshot; they must not declare the capability, so guard-dependent optimizations stay off against them even when the flag is set.
|
|
56
|
+
- The guard only ever rejects on evidence, and it fails open in every other case: a backend that cannot decide — because its record of recent events is incomplete, has expired, or covers only part of the run's history — must accept the write. A rejection therefore always means the snapshot really was incomplete, but the absence of one does not prove it was complete. Busy runs (wide step fan-outs, high hook volume) are the most likely to skip the check.
|
|
57
|
+
- As a result, 412 volume describes a workload rather than the health of a deployment, and a run that never sees one is not evidence the guard is inactive.
|
|
49
58
|
- Set `0` to disable.
|
|
50
59
|
|
|
60
|
+
### `WORKFLOW_PRECONDITION_MAX_INPROCESS_RESTARTS`
|
|
61
|
+
|
|
62
|
+
- Default: `3`
|
|
63
|
+
- How many times a single invocation restarts its replay in-process after a rejected event creation before it falls back to a re-invocation.
|
|
64
|
+
- A restart reloads the event log and rebuilds the workflow from scratch, so it costs a replay but no queue round trip. A World may attach the missing events to its rejection, in which case the first restart needs no event-log request at all.
|
|
65
|
+
|
|
66
|
+
### `WORKFLOW_PRECONDITION_MAX_REINVOCATIONS`
|
|
67
|
+
|
|
68
|
+
- Default: `5`
|
|
69
|
+
- How many re-invocations one run may spend on rejected event creations before it is failed with `RUNTIME_ERROR`.
|
|
70
|
+
- Counted on the run's queue messages rather than per invocation, because a re-invocation enqueues a fresh message and so restarts the ordinary delivery count. Without this budget a run whose event log keeps growing faster than it can be read would cycle indefinitely.
|
|
71
|
+
|
|
72
|
+
### `WORKFLOW_PRECONDITION_REINVOKE_DELAY_SECONDS`
|
|
73
|
+
|
|
74
|
+
- Default: `2`
|
|
75
|
+
- Delay before a re-invocation caused by a rejected event creation.
|
|
76
|
+
- Unlike an in-process restart, which re-reads immediately, a re-invocation only happens once the in-process budget failed to catch up — so the delay gives the other writers a moment to quiesce.
|
|
77
|
+
|
|
51
78
|
## Inline execution
|
|
52
79
|
|
|
53
80
|
### `WORKFLOW_V2_TIMEOUT_MS`
|
|
@@ -115,6 +142,14 @@ For example, a workflow can run a 10-minute inline step even with `WORKFLOW_REPL
|
|
|
115
142
|
- Debug log filter with wildcards and negation.
|
|
116
143
|
- Examples: `workflow:*`, `workflow:*,-workflow:telemetry:*`.
|
|
117
144
|
|
|
145
|
+
## Transport
|
|
146
|
+
|
|
147
|
+
### `WORKFLOW_H2_MULTIPLEX`
|
|
148
|
+
|
|
149
|
+
- Default: enabled
|
|
150
|
+
- On the Vercel World, lets concurrent event-log requests share one HTTP/2 connection instead of one connection per in-flight request.
|
|
151
|
+
- Set `0` to send one event request per connection.
|
|
152
|
+
|
|
118
153
|
## Queue namespace
|
|
119
154
|
|
|
120
155
|
### `WORKFLOW_QUEUE_NAMESPACE`
|
|
@@ -21,11 +21,11 @@ A [World](/docs/deploying) stores workflow state and delivers queue messages.
|
|
|
21
21
|
|
|
22
22
|
Outside Vercel, Workflow defaults to the Local World. On Vercel, leave `WORKFLOW_TARGET_WORLD` unset for the normal case; Workflow detects the Vercel deployment and selects the Vercel World automatically.
|
|
23
23
|
|
|
24
|
-
The World is selected when your app
|
|
24
|
+
The World is selected when your app **runs**, from the environment of the process serving it, so changing `WORKFLOW_TARGET_WORLD` takes effect on the next start without a rebuild. Detection keys off `VERCEL_DEPLOYMENT_ID`, which Vercel sets in every deployed function and nothing else sets: with it, the Vercel World; without it, the Local World.
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Broader signals are deliberately ignored. `vercel env pull` writes `VERCEL=1` into `.env.local`, so a dev server or a production server started on your own machine sees it while running against a writable filesystem — where the Local World is the right choice. Set `WORKFLOW_TARGET_WORLD=vercel` explicitly if you want such a process to talk to the Vercel World; starting a run then fails with an error naming the missing `VERCEL_DEPLOYMENT_ID`.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
A deployment that pins `WORKFLOW_TARGET_WORLD=local` warns at startup and fails on its first write, because a Vercel deployment's filesystem is read-only.
|
|
29
29
|
|
|
30
30
|
Set `WORKFLOW_TARGET_WORLD` only when you want to use a custom or self-hosted World:
|
|
31
31
|
|
|
@@ -86,6 +86,18 @@ The Local World is the default outside Vercel and is intended for development.
|
|
|
86
86
|
- Default: unlimited
|
|
87
87
|
- Maximum seconds a local queue message stays hidden before the handler rechecks the run.
|
|
88
88
|
|
|
89
|
+
### `WORKFLOW_LOCAL_HEADERS_TIMEOUT_MS`
|
|
90
|
+
|
|
91
|
+
- Factory option: none
|
|
92
|
+
- Default: `30000`
|
|
93
|
+
- Maximum milliseconds to wait for a local queue handler to begin responding before the durable message is redelivered. Set to `0` to disable.
|
|
94
|
+
|
|
95
|
+
### `WORKFLOW_LOCAL_BODY_TIMEOUT_MS`
|
|
96
|
+
|
|
97
|
+
- Factory option: none
|
|
98
|
+
- Default: `30000`
|
|
99
|
+
- Maximum gap in milliseconds between response body chunks from a local queue handler before the durable message is redelivered. Set to `0` to disable.
|
|
100
|
+
|
|
89
101
|
### `recoverActiveRuns`
|
|
90
102
|
|
|
91
103
|
- Environment variable: `WORKFLOW_LOCAL_RECOVER_ACTIVE_RUNS`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workflow",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.39",
|
|
4
4
|
"description": "Workflow SDK - Build durable, resilient, and observable workflows",
|
|
5
5
|
"main": "dist/typescript-plugin.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -59,18 +59,18 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"ms": "2.1.3",
|
|
62
|
-
"@workflow/astro": "5.0.0-beta.
|
|
63
|
-
"@workflow/cli": "5.0.0-beta.
|
|
64
|
-
"@workflow/core": "5.0.0-beta.
|
|
65
|
-
"@workflow/errors": "5.0.0-beta.
|
|
62
|
+
"@workflow/astro": "5.0.0-beta.39",
|
|
63
|
+
"@workflow/cli": "5.0.0-beta.39",
|
|
64
|
+
"@workflow/core": "5.0.0-beta.39",
|
|
65
|
+
"@workflow/errors": "5.0.0-beta.15",
|
|
66
66
|
"@workflow/typescript-plugin": "5.0.0-beta.5",
|
|
67
|
-
"@workflow/utils": "5.0.0-beta.
|
|
68
|
-
"@workflow/next": "5.0.0-beta.
|
|
69
|
-
"@workflow/nest": "5.0.0-beta.
|
|
70
|
-
"@workflow/nitro": "5.0.0-beta.
|
|
71
|
-
"@workflow/nuxt": "5.0.0-beta.
|
|
72
|
-
"@workflow/sveltekit": "5.0.0-beta.
|
|
73
|
-
"@workflow/rollup": "5.0.0-beta.
|
|
67
|
+
"@workflow/utils": "5.0.0-beta.8",
|
|
68
|
+
"@workflow/next": "5.0.0-beta.39",
|
|
69
|
+
"@workflow/nest": "5.0.0-beta.39",
|
|
70
|
+
"@workflow/nitro": "5.0.0-beta.39",
|
|
71
|
+
"@workflow/nuxt": "5.0.0-beta.39",
|
|
72
|
+
"@workflow/sveltekit": "5.0.0-beta.39",
|
|
73
|
+
"@workflow/rollup": "5.0.0-beta.39"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@types/ms": "2.1.0",
|