Skip to content

workflow@5.3.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 22:47
Immutable release. Only release title and notes can be modified.
e0245be

@workflow/core@5.3.0

  • #5100 2be58c2 @VaguelySerious - Let a parallel branch start its next inline step without waiting for its slower siblings (spec 8 runs on the Node.js VM). A run now ends as soon as the workflow returns or throws, even while a Promise.race loser is still running inline; that loser gets only its current attempt, and its step events can follow run_completed. Set WORKFLOW_INLINE_EARLY_ADVANCE=0 to restore the previous behavior.
  • #5091 b8e1f1b @karthikscale3 - Reuse the Hook returned by getHookByToken() with resumeHook() to skip the token lookup on later deliveries, including across JSON or other ordinary serialization. Capable Worlds enforce atomic deduplication on cached deliveries. The SDK falls back internally after definite pre-write refusals, retries admission throttles, and never re-sends an uncertain resolved write. Trace attributes identify resolved deliveries and fallback refusals.
  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.
  • #4996 eb07a8d @alangenfeld - Add start(workflow, args, { hook: { token, metadata, experimental_minRetention } }), which admits the run and creates its start Hook in one atomic step, and throws HookConflictError naming the owner for a duplicate, which never becomes a run. resumeHook(token) works as soon as the run is admitted, and payloads sent before the workflow calls createHook({ token }) are delivered in order once it does; that createHook() binds to the start Hook without registering a new one. Disposing the start Hook releases the token immediately; otherwise the run's end releases it, after any experimental_minRetention (there is no default retention). cancel() of a candidate that never became a run fences it.
  • #5081 e127948 @karthikscale3 - Use length-prefixed frames for real-time abort stream packets. Keep readers compatible with existing unframed packets, reassemble split transport reads, and retain unframed writes for older cross-deployment targets and hook resumptions without an attested receiving runtime. Payload encryption and durable hook events are unchanged.
  • #5041 7d31a0a @alangenfeld - Close a stream read that is cancelled while it is still connecting, so a fast signal-bearing step no longer leaves its abort-stream read open until the server's max duration.
  • #5183 a54154e @VaguelySerious - Stop Astro and Vite from warning about generated workflow files during build and dev.
  • #4990 3837f92 @pranaygp - Skip redundant hook disposal events when a workflow completes or fails.
  • #5018 ef5f004 @pranaygp - Run steps started beside an awaited hook.getConflict() inline instead of handing them to the queue: the suspension now defers their creates, settles the awaiter off the hook write, and runs the bodies on the pass after it. Those steps now share one inline batch with whatever the settled awaiter started, so work the awaiter's branch begins after its own first step waits for them — where queueing put the branch in a separate invocation. Steps past WORKFLOW_MAX_INLINE_STEPS are unaffected and still queue.
  • #4661 3bf8cd9 @VaguelySerious - With WORKFLOW_VM=quickjs, replay ignores events for a step, wait or hook after its terminal event, as the default engine does.
  • #4945 7e221fc @TooTallNate - Keep the QuickJS VM heap flat over long runs: settled steps, sleeps, attributes and disposed hooks are released instead of retained (with their step arguments) for the rest of the run, and event replay no longer scans every operation the run ever created.
  • #5070 b9d618a @alangenfeld - Forward the run's encryptionPublicKey on a resilient run_started, so a run created from its queued copy can still receive sealed writes.
  • #5115 cc637c4 @VaguelySerious - Retry steps whose stream encryption key lookup fails transiently instead of failing them with a SerializationError
  • #5053 af8c6d3 @NishitaSikka - Fix a step that could be created and never run when two executions of it met in one process and the first one's claim lost.
  • #5156 44d7c76 @alangenfeld - The single-orchestrator engine admits start({ hook }) candidates: their first delivery skips turbo, run_started carries the start Hook request, a refused candidate acknowledges without running code, and the workflow's createHook({ token }) binds to the start Hook.
  • #4996 eb07a8d @alangenfeld - Trace start({ hook }) outcomes: rejection reasons on WorkflowWorldError.reason, an outcome on every exit of the start span and on a queued copy's invocation span, a reason for every holder wake, and debug logs of local and Postgres admission decisions.
  • #5184 997b03d @VaguelySerious - Fix webhook and workflow URLs using port 3000 instead of the server's port when @workflow/utils is not a direct dependency
  • #5187 433b345 @VaguelySerious - Support reading response.body with getReader() inside workflow functions, fixing AI SDK calls through the workflow fetch on current ai versions. The QuickJS engine also no longer fails to serialize step arguments such as fetch options that contain signal: undefined.

@workflow/cli@5.0.7

  • #5182 7f33693 @VaguelySerious - Respect --project and --team over the inferred .vercel link, and prefer the nearest .vercel/project.json in monorepos
  • #4996 eb07a8d @alangenfeld - Show a run's start Hook token and its hook_created (from run_created) in the timeline, and revive WorkflowStartError; CLI re-runs never forward a start Hook. Ship this before or with the SDK release: older dashboards and CLIs cannot revive the new error.

@workflow/world@5.1.0

  • #5091 b8e1f1b @karthikscale3 - Reuse the Hook returned by getHookByToken() with resumeHook() to skip the token lookup on later deliveries, including across JSON or other ordinary serialization. Capable Worlds enforce atomic deduplication on cached deliveries. The SDK falls back internally after definite pre-write refusals, retries admission throttles, and never re-sends an uncertain resolved write. Trace attributes identify resolved deliveries and fallback refusals.
  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.
  • #4996 eb07a8d @alangenfeld - Add the atomic start Hook admission contract: startHook on run_created, the resilient run_started and the queued run input, the atomicStartHook capability, startHookId(), WorkflowStartError, the START_HOOK_ADMISSION_DISABLED and START_HOOK_CANDIDATE_CANCELLED codes, and a conformance suite. Admission creates the run's start Hook in the same atomic step: run_created stands for its hook_created, it accepts deliveries while the run is still pending, and it then follows the ordinary Hook lifecycle. HookConflictError gains kind: 'start' for a refused start.
  • #5070 b9d618a @alangenfeld - Forward the run's encryptionPublicKey on a resilient run_started, so a run created from its queued copy can still receive sealed writes.
  • #4945 7e221fc @TooTallNate - Bump SNAPSHOT_FORMAT_VERSION to 4 for the QuickJS engine's new pending-operation heap layout.
  • #4996 eb07a8d @alangenfeld - Trace start({ hook }) outcomes: rejection reasons on WorkflowWorldError.reason, an outcome on every exit of the start span and on a queued copy's invocation span, a reason for every holder wake, and debug logs of local and Postgres admission decisions.

@workflow/world-local@5.2.0

  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.
  • #4996 eb07a8d @alangenfeld - Support atomic start Hook admission: admitting a run creates its start Hook, which is resumable at once and then follows the ordinary Hook lifecycle.
  • #5000 3ca3bf0 @Mark-Lasfar - Take over a run's in-band fence lock at once when its holder is known to be dead (its pid is gone on this host), instead of stalling in-band writes on that run for 30 s after the holder was killed
  • #4996 eb07a8d @alangenfeld - Trace start({ hook }) outcomes: rejection reasons on WorkflowWorldError.reason, an outcome on every exit of the start span and on a queued copy's invocation span, a reason for every holder wake, and debug logs of local and Postgres admission decisions.
  • #5145 2a3e4c0 @VaguelySerious - Fix a start() or resumeHook() called from another process on the same data directory (a script or test runner) overlapping the app's own deliveries of the run and getting its writes refused by the in-band fence on spec 9 runs.
  • #4940 6455beb @AndrewBarba - Restart recovery now dispatches steps that were running inline when the previous process exited right away instead of after the 860s inline-ownership lease, and releaseOrphanedSteps(runId) exposes the same release to embedders that recover runs themselves.
  • #4661 3bf8cd9 @VaguelySerious - Hold a queue concurrency slot for each delivery, not across the sleeps and backoffs between deliveries.
  • #4661 3bf8cd9 @VaguelySerious - Back off retries of a queue message whose deliveries keep failing after 32 attempts, as Vercel Queues does.
  • #5069 72131a2 @AndrewBarba - Deliver stream chunks in the order they were written. A reader that opened, or polled, while chunks were being written could get a later chunk before an earlier one, and could get a chunk twice. Writes to one stream now land in order, including a writeMulti group and concurrent writes, and the reader holds live chunks while it reads from disk.
  • #4909 d4b7b06 @fazxes - Name each stream chunk as it lands, after every chunk already in the stream, so a write that stalled before landing no longer lands ahead of chunks a reader already read.

@workflow/world-postgres@5.1.0

  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.
  • #4996 eb07a8d @alangenfeld - Support start({ hook }) behind WORKFLOW_POSTGRES_EXPERIMENTAL_START_HOOK=1 (migration 0028_add_start_hook_admissions): admitting a run creates its start Hook in the same transaction, so the Hook resolves and accepts resumes as soon as start() returns. Every Hook now claims its token through a unique index, so an admission and a concurrent createHook() can no longer both win; the migration is required even with the flag off, and every process on the database must run this version before you enable it.
  • #4759 c07a6a3 @pranaygp - Add jobLockStaleSeconds (WORKFLOW_POSTGRES_JOB_LOCK_STALE_SECONDS, default 0, off). When set, a running delivery renews its Graphile job lock, and a job whose process died is redelivered by another process once its lock has gone unrenewed for that many seconds, instead of after Graphile Worker's fixed 4 hours or the next restart. 30 is a good value when more than one process shares the database. It's off by default because of rolling upgrades: processes on an earlier version don't renew their locks, so turn it on once every process that shares the database runs this version.
  • #4761 8a17d00 @pranaygp - Scope startup recovery to the World's jobPrefix: start() re-enqueues only the active runs created under its own prefix (plus unprefixed runs from earlier versions), so apps that share a database no longer drive each other's runs after a restart. A migration adds workflow_runs.job_prefix; run bootstrap before deploying.
  • #5136 62c8a23 @alangenfeld - A run_started that races the run ending no longer moves the run back to running; it's refused with RunExpiredError.
  • #5053 af8c6d3 @NishitaSikka - Every keyed job now keeps its first scheduled delivery time (preserve_run_at), so an immediate duplicate cannot erase a delayed retry's backoff.
  • #4996 eb07a8d @alangenfeld - Trace start({ hook }) outcomes: rejection reasons on WorkflowWorldError.reason, an outcome on every exit of the start span and on a queued copy's invocation span, a reason for every holder wake, and debug logs of local and Postgres admission decisions.

@workflow/world-vercel@5.3.0

  • #5091 b8e1f1b @karthikscale3 - Reuse the Hook returned by getHookByToken() with resumeHook() to skip the token lookup on later deliveries, including across JSON or other ordinary serialization. Capable Worlds enforce atomic deduplication on cached deliveries. The SDK falls back internally after definite pre-write refusals, retries admission throttles, and never re-sends an uncertain resolved write. Trace attributes identify resolved deliveries and fallback refusals.
  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.
  • #4996 eb07a8d @alangenfeld - Send startHook on run creation and map start Hook answers, retrying a delivery to a start Hook whose run is still being created, honoring Retry-After; atomicStartHook is advertised only with WORKFLOW_VERCEL_EXPERIMENTAL_START_HOOK=1, which needs a backend that supports start Hooks.
  • #4996 eb07a8d @alangenfeld - Trace start({ hook }) outcomes: rejection reasons on WorkflowWorldError.reason, an outcome on every exit of the start span and on a queued copy's invocation span, a reason for every holder wake, and debug logs of local and Postgres admission decisions.
  • #5072 612c5f4 @alangenfeld - Name the fields a v4 createEvent response failed its schema on in the error message.
  • #5043 1123ea6 @pranaygp - Upgrade @vercel/queue to 0.10.0 and publish a fan-out's batched step dispatches through the now-stable sendBatch instead of the deprecated experimental_sendBatch
  • #4994 5dc9e15 @neilverc - Stop following HTTP redirects on workflow API requests. fetch strips Authorization across origins but forwards every other header, so a redirect carried the request's x-vercel-trusted-oidc-idp-token to the host named in Location. A 3xx now surfaces as an error, matching the node:http transport.

@workflow/world-testing@5.0.7

  • #4990 3837f92 @pranaygp - Verify terminal cleanup releases non-retained hook tokens and avoid comparing fence counters with a stale event listing.
  • #5073 5f5299b @alangenfeld - Wait for run_completed to be listed before comparing a run's event reads in the resolveData check.
  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.

@workflow/web@5.0.7

  • #5079 f4f6b02 @karthikscale3 - Recognize unframed serialized abort packets in the Streams viewer so encrypted packets can be decrypted, and keep stream-list rows at least 40px tall.

@workflow/web-shared@5.0.7

  • #4996 eb07a8d @alangenfeld - Show a run's start Hook token and its hook_created (from run_created) in the timeline, and revive WorkflowStartError; CLI re-runs never forward a start Hook. Ship this before or with the SDK release: older dashboards and CLIs cannot revive the new error.

@workflow/builders@5.0.7

  • #5183 a54154e @VaguelySerious - Stop Astro and Vite from warning about generated workflow files during build and dev.
  • #4999 aed1a0d @joelfickson - Fix module error reporting when the offending import spans multiple lines, and fix multi-line imports not being checked for modules correctly.

@workflow/astro@5.0.7

@workflow/errors@5.1.0

  • #4996 eb07a8d @alangenfeld - Add the atomic start Hook admission contract: startHook on run_created, the resilient run_started and the queued run input, the atomicStartHook capability, startHookId(), WorkflowStartError, the START_HOOK_ADMISSION_DISABLED and START_HOOK_CANDIDATE_CANCELLED codes, and a conformance suite. Admission creates the run's start Hook in the same atomic step: run_created stands for its hook_created, it accepts deliveries while the run is still pending, and it then follows the ordinary Hook lifecycle. HookConflictError gains kind: 'start' for a refused start.
  • #5115 cc637c4 @VaguelySerious - Retry steps whose stream encryption key lookup fails transiently instead of failing them with a SerializationError
  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.
  • #4996 eb07a8d @alangenfeld - Trace start({ hook }) outcomes: rejection reasons on WorkflowWorldError.reason, an outcome on every exit of the start span and on a queued copy's invocation span, a reason for every holder wake, and debug logs of local and Postgres admission decisions.

@workflow/vitest@5.0.7

  • #4661 3bf8cd9 @VaguelySerious - Add opt-in spec 9 runs, driven by a single orchestrator per run: set WORKFLOW_SPEC_VERSION=9. New runs stay on spec 8 by default.