Repository navigation
workflow: bootstrap the run from run_started - #284
Merged
Merged
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
fantix
force-pushed
the
workflow-resilient-start-consumer
branch
from
August 11, 2026 22:40
898fa86 to
04763ff
Compare
fantix
force-pushed
the
workflow-resilient-start-consumer
branch
from
August 12, 2026 02:34
04763ff to
ce4fe09
Compare
3 tasks done
fantix
force-pushed
the
workflow-resilient-start-consumer
branch
from
August 13, 2026 14:58
ce4fe09 to
2edb224
Compare
elprans
approved these changes
Aug 13, 2026
fantix
force-pushed
the
workflow-resilient-start-consumer
branch
from
August 13, 2026 22:57
2edb224 to
3a404d7
Compare
The handler opened by reading the run, which made a race in `start()` fatal: it does not order its `run_created` write against the queue push, so a delivery can arrive before the row exists. The read 404s, the queue does not redeliver, and the run never runs. On the e2e Vercel lane that cost roughly one arbitrary run per suite, on a different fixture each time, which reads as flakiness and is not. Write `run_started` first instead. It transitions the run and returns the entity, so the read was a round-trip we did not need, and on a run whose row has not landed it is the write that creates it from the `runInput` the message carried. Refuse a delivery whose `runInput` names another environment before that write, or resilient start would fork the run id across two tenants. The check skips when either side is unknown.
fantix
force-pushed
the
workflow-resilient-start-consumer
branch
from
August 13, 2026 23:00
3a404d7 to
b9912df
Compare
Merged
scotttrinh
added a commit
that referenced
this pull request
Aug 26, 2026
vercel-internal-core -------------------- 0.1.3 - 2026-08-26 ------------------ Internal -------- - Support disabling HTTP timeouts for selected SDK operations while preserving the client default elsewhere. (#307) vercel-connect -------------- 0.1.1 - 2026-08-26 ------------------ - Update dependencies. vercel-queue ------------ 0.8.1 - 2026-08-26 ------------------ Documentation ------------- - Remove documentation and examples for `asgi_app` in preparation for its removal. (#309) vercel-sandbox -------------- 0.5.0 - 2026-08-26 ------------------ Features -------- - Add sync and async `fork_sandbox(...)` support for creating a sandbox from an existing named sandbox with optional configuration overrides. (#257) - Add `region` and `failover_regions` configuration for sandbox creation, forks, and updates, plus multi-region snapshot availability reporting. (#308) Bug Fixes --------- - Allow Sandbox process waits and log streams to remain idle longer than the session HTTP timeout. (#307) vercel-workflow --------------- 0.10.0 - 2026-08-26 ------------------- Breaking Changes ---------------- - Use type annotations on workflows and step to allow passing Pydantic models and dataclasses. (#317) - This is a breaking change, because type annotations will now be enforced. Passing a `dict` when the declaration expects a `list` will fail. (#317) - Pydantic models and dataclasses can no longer be passed to `@serializable` or `register_serializable()`. Annotate the workflow or step parameter or return value with their type instead. (#317) Features -------- - `get_workflow_metadata()` returns the current run's `WorkflowInfo` (run id, workflow name, start time, deployment URL, and feature flags), callable from a workflow body or a step body — mirroring the JS SDK's `getWorkflowMetadata()`. (#320) - One current limitation is that `started_at` is `None` from inside a step. (#320) - `BaseHook.wait()` accepts `metadata` to record on the hook, and `get_hook_by_token()` reads it back for a resumer. (#301) - A step can raise `RetryableError` to control when its next attempt runs. (#302) - Accept `specVersion` 7 sealed noop event logs. (#319) - A workflow or step can attach plaintext metadata to its run with `set_attributes()`. (#303) - Add a `share_sandboxes` parameter to `SandboxPolicy` to enable reusing already created sandboxes instead of creating a new one on each invocation. This speeds up workflows but means that modifications to global state may persist between invocations. (#310) - Expose unstable API to serve workflow HTTP endpoint from your own web framework. (#294) - Added semi-internal manifest API for TS tools and e2e test. (#296) Bug Fixes --------- - Fix failing or even crashing cipher calls inside the workflow sandbox. (#305) - Support resuming hooks with payload in the queue message. (#300) - Fixed nulls rejected by server, requiring Pydantic 2.12 or newer. (#321) - Fixed workflow and step calls with both positional-or-keyword parameters and `*args` failing during replay because their arguments were recorded in an unbindable shape. (#312) Internal -------- - Construct the protocol models by Python field name. (#322) vercel ------ 0.11.0 - 2026-08-26 ------------------- Features -------- - Expose `get_deadline()` for reading the current Function invocation deadline. (#306) - Answer workflow health checks for both queue-based transport and HTTP. (#292) - Add support to read the sealed (`encp`) workflow payloads (X25519 + AES-GCM) an outside writer addresses to a run, under the `encryption` extra. (#297) Bug Fixes --------- - Remove upper bounds on aggregate Sandbox and Workflow dependencies so sibling releases cannot make the `vercel` package un-installable. (#334) - Start a workflow run even when its queue message arrives before the `run_created` event has landed. (#284) Internal -------- - The Workflows implementation now ships in the separate `vercel-workflow` distribution, which `vercel` depends on, so `vercel.workflow` imports keep working without installing anything extra. (#299) vercel-apscheduler ------------------ 0.3.0 - 2026-08-26 ------------------ Breaking Changes ---------------- - The managed Redis backend was removed. The integration now always runs on its managed job store (Vercel Runtime Cache); a configured default `RedisJobStore` is rejected at import, `VERCEL_APSCHEDULER_BACKEND` accepts only `cache`, and the `redis` dependency is gone. The scheduler's durable identity now always derives from the builder-assigned subscriber id (previously the Redis `jobs_key`); the `scheduler_id` option still pins an identity explicitly. (#286) vercel-celery ------------- 0.7.5 - 2026-08-26 ------------------ - Update dependencies. vercel-django-tasks ------------------- 0.7.0 - 2026-08-26 ------------------ Features -------- - Add a Vercel Queues backend for Django Tasks and use it by default when no task backends are configured. (#291) vercel-dramatiq --------------- 0.7.4 - 2026-08-26 ------------------ - Update dependencies.
scotttrinh
added a commit
that referenced
this pull request
Aug 31, 2026
vercel-headers -------------- 0.7.2 - 2026-08-31 ------------------ Bug Fixes --------- - Accept request objects with concrete header implementations in the IP address and geolocation type annotations. (#337) vercel-internal-core -------------------- 0.1.3 - 2026-08-31 ------------------ Internal -------- - Support disabling HTTP timeouts for selected SDK operations while preserving the client default elsewhere. (#307) vercel-oidc ----------- 0.8.1 - 2026-08-31 ------------------ - Update dependencies. vercel-connect -------------- 0.1.1 - 2026-08-31 ------------------ - Update dependencies. vercel-internal-telemetry ------------------------- 0.7.3 - 2026-08-31 ------------------ - Update dependencies. vercel-queue ------------ 0.8.1 - 2026-08-31 ------------------ Bug Fixes --------- - Force embedded development servers to exit when graceful shutdown stalls. (#351) Documentation ------------- - Remove documentation and examples for `asgi_app` in preparation for its removal. (#309) vercel-sandbox -------------- 0.5.0 - 2026-08-31 ------------------ Features -------- - Add sync and async `fork_sandbox(...)` support for creating a sandbox from an existing named sandbox with optional configuration overrides. (#257) - Add `region` and `failover_regions` configuration for sandbox creation, forks, and updates, plus multi-region snapshot availability reporting. (#308) - Forward private ``__``-prefixed parameters to the Sandbox API. (#350) Bug Fixes --------- - Allow Sandbox process waits and log streams to remain idle longer than the session HTTP timeout. (#307) - Expose Linux process signals consistently on every SDK host platform. (#352) vercel-cache ------------ 0.7.3 - 2026-08-31 ------------------ - Update dependencies. vercel-workflow --------------- 0.10.0 - 2026-08-31 ------------------- Breaking Changes ---------------- - Make sleep() and retry delays treat numbers as seconds, not ms (#346) - This matches Python standard library APIs. (#346) - Use type annotations on workflows and step to allow passing Pydantic models and dataclasses. (#317) - This is a breaking change, because type annotations will now be enforced. Passing a `dict` when the declaration expects a `list` will fail. (#317) - Pydantic models and dataclasses can no longer be passed to `@serializable` or `register_serializable()`. Annotate the workflow or step parameter or return value with their type instead. (#317) Features -------- - Support `call_later`, `call_at`, and `now` in the event loop implementation. (#343) - This enables use of `asyncio.sleep()` as well as `asyncio.timeout` and the `timeout` parameter of `asyncio.wait_for`. (#343) - `get_workflow_metadata()` returns the current run's `WorkflowInfo` (run id, workflow name, start time, deployment URL, and feature flags), callable from a workflow body or a step body — mirroring the JS SDK's `getWorkflowMetadata()`. (#320) - One current limitation is that `started_at` is `None` from inside a step. (#320) - `BaseHook.wait()` accepts `metadata` to record on the hook, and `get_hook_by_token()` reads it back for a resumer. (#301) - A step can raise `RetryableError` to control when its next attempt runs. (#302) - Accept `specVersion` 7 sealed noop event logs. (#319) - Failed run and step events now preserve serialized error classes, messages, stacks, and causes. Failed runs also expose a plaintext `errorCode`. (#304) - A workflow or step can attach plaintext metadata to its run with `set_attributes()`. (#303) - Add a `share_sandboxes` parameter to `SandboxPolicy` to enable reusing already created sandboxes instead of creating a new one on each invocation. This speeds up workflows but means that modifications to global state may persist between invocations. (#310) - Support `timedelta` arguments for workflow `sleep()` and retry delays. (#342) - Expose unstable API to serve workflow HTTP endpoint from your own web framework. (#294) - Added semi-internal manifest API for TS tools and e2e test. (#296) Bug Fixes --------- - Fix failing or even crashing cipher calls inside the workflow sandbox. (#305) - Fail a workflow run with `HookConflictError` when another run already owns its hook token instead of leaving it running indefinitely. (#327) - Support resuming hooks with payload in the queue message. (#300) - Fix some bugs involving hooks arriving when the workflow was not yet blocked on them. (#339) - Fixed nulls rejected by server, requiring Pydantic 2.12 or newer. (#321) - Prevent workflows from having side effects while suspending. (#332) - `hook.dispose()` will now work properly in a `finally` block. (That is, the hook will be disposed only when the workflow is actually terminating, and not every time it gets replayed.) (#332) - More reliably fail runs whose replay diverges from the event log. (#347) - Runs will now fail even in the case where the main thread of execution is not directly blocked on the suspension that is erroring. (#347) - Fixed workflow and step calls with both positional-or-keyword parameters and `*args` failing during replay because their arguments were recorded in an unbindable shape. (#312) Internal -------- - Remove a just-added return from a finally block. (#344) - Correct internal workflow type annotations found by checking untyped function bodies. (#337) - Refactored event replay. (#341) - Construct the protocol models by Python field name. (#322) vercel ------ 0.11.0 - 2026-08-31 ------------------- Features -------- - Expose `get_deadline()` for reading the current Function invocation deadline. (#306) - Answer workflow health checks for both queue-based transport and HTTP. (#292) - Add support to read the sealed (`encp`) workflow payloads (X25519 + AES-GCM) an outside writer addresses to a run, under the `encryption` extra. (#297) Bug Fixes --------- - Remove upper bounds on aggregate Sandbox and Workflow dependencies so sibling releases cannot make the `vercel` package un-installable. (#334) - Start a workflow run even when its queue message arrives before the `run_created` event has landed. (#284) Internal -------- - The Workflows implementation now ships in the separate `vercel-workflow` distribution, which `vercel` depends on, so `vercel.workflow` imports keep working without installing anything extra. (#299) vercel-apscheduler ------------------ 0.3.0 - 2026-08-31 ------------------ Breaking Changes ---------------- - The managed Redis backend was removed. The integration now always runs on its managed job store (Vercel Runtime Cache); a configured default `RedisJobStore` is rejected at import, `VERCEL_APSCHEDULER_BACKEND` accepts only `cache`, and the `redis` dependency is gone. The scheduler's durable identity now always derives from the builder-assigned subscriber id (previously the Redis `jobs_key`); the `scheduler_id` option still pins an identity explicitly. (#286) vercel-celery ------------- 0.7.5 - 2026-08-31 ------------------ - Update dependencies. vercel-django-tasks ------------------- 0.7.0 - 2026-08-31 ------------------ Features -------- - Add a Vercel Queues backend for Django Tasks and use it by default when no task backends are configured. (#291) vercel-dramatiq --------------- 0.7.4 - 2026-08-31 ------------------ - Update dependencies.
scotttrinh
added a commit
that referenced
this pull request
Aug 31, 2026
vercel-headers -------------- 0.7.2 - 2026-08-31 ------------------ Bug Fixes --------- - Accept request objects with concrete header implementations in the IP address and geolocation type annotations. (#337) vercel-internal-core -------------------- 0.1.3 - 2026-08-31 ------------------ Internal -------- - Support disabling HTTP timeouts for selected SDK operations while preserving the client default elsewhere. (#307) vercel-oidc ----------- 0.8.1 - 2026-08-31 ------------------ - Update dependencies. vercel-connect -------------- 0.1.1 - 2026-08-31 ------------------ - Update dependencies. vercel-internal-telemetry ------------------------- 0.7.3 - 2026-08-31 ------------------ - Update dependencies. vercel-queue ------------ 0.8.1 - 2026-08-31 ------------------ Bug Fixes --------- - Force embedded development servers to exit when graceful shutdown stalls. (#351) Documentation ------------- - Remove documentation and examples for `asgi_app` in preparation for its removal. (#309) vercel-sandbox -------------- 0.5.0 - 2026-08-31 ------------------ Features -------- - Add sync and async `fork_sandbox(...)` support for creating a sandbox from an existing named sandbox with optional configuration overrides. (#257) - Add `region` and `failover_regions` configuration for sandbox creation, forks, and updates, plus multi-region snapshot availability reporting. (#308) - Forward private ``__``-prefixed parameters to the Sandbox API. (#350) Bug Fixes --------- - Allow Sandbox process waits and log streams to remain idle longer than the session HTTP timeout. (#307) - Expose Linux process signals consistently on every SDK host platform. (#352) vercel-cache ------------ 0.7.3 - 2026-08-31 ------------------ - Update dependencies. vercel-workflow --------------- 0.10.0 - 2026-08-31 ------------------- Breaking Changes ---------------- - Make `await hook` never return `None` - Raises a new `HookDisposedError` instead of returning `None` when the hook has been disposed. It is now typed to return `T` instead of `T | None`. `async for` over a hook will stop iterating on disposal, still. - Make sleep() and retry delays treat numbers as seconds, not ms (#346) - This matches Python standard library APIs. (#346) - Use type annotations on workflows and step to allow passing Pydantic models and dataclasses. (#317) - This is a breaking change, because type annotations will now be enforced. Passing a `dict` when the declaration expects a `list` will fail. (#317) - Pydantic models and dataclasses can no longer be passed to `@serializable` or `register_serializable()`. Annotate the workflow or step parameter or return value with their type instead. (#317) Features -------- - Support `call_later`, `call_at`, and `now` in the event loop implementation. (#343) - This enables use of `asyncio.sleep()` as well as `asyncio.timeout` and the `timeout` parameter of `asyncio.wait_for`. (#343) - `get_workflow_metadata()` returns the current run's `WorkflowInfo` (run id, workflow name, start time, deployment URL, and feature flags), callable from a workflow body or a step body — mirroring the JS SDK's `getWorkflowMetadata()`. (#320) - One current limitation is that `started_at` is `None` from inside a step. (#320) - Make `HookEvent` an async context manager - This matches TS, which supports `using`. ``` # disposes the hook on block exit async with SomeHook.wait(...) as hook: res = await hook ``` - `BaseHook.wait()` accepts `metadata` to record on the hook, and `get_hook_by_token()` reads it back for a resumer. (#301) - A step can raise `RetryableError` to control when its next attempt runs. (#302) - Accept `specVersion` 7 sealed noop event logs. (#319) - Failed run and step events now preserve serialized error classes, messages, stacks, and causes. Failed runs also expose a plaintext `errorCode`. (#304) - A workflow or step can attach plaintext metadata to its run with `set_attributes()`. (#303) - Add a `share_sandboxes` parameter to `SandboxPolicy` to enable reusing already created sandboxes instead of creating a new one on each invocation. This speeds up workflows but means that modifications to global state may persist between invocations. (#310) - Support `timedelta` arguments for workflow `sleep()` and retry delays. (#342) - Expose unstable API to serve workflow HTTP endpoint from your own web framework. (#294) - Added semi-internal manifest API for TS tools and e2e test. (#296) Bug Fixes --------- - Fix failing or even crashing cipher calls inside the workflow sandbox. (#305) - Fail a workflow run with `HookConflictError` when another run already owns its hook token instead of leaving it running indefinitely. (#327) - Support resuming hooks with payload in the queue message. (#300) - Fix some bugs involving hooks arriving when the workflow was not yet blocked on them. (#339) - Fixed nulls rejected by server, requiring Pydantic 2.12 or newer. (#321) - Prevent workflows from having side effects while suspending. (#332) - `hook.dispose()` will now work properly in a `finally` block. (That is, the hook will be disposed only when the workflow is actually terminating, and not every time it gets replayed.) (#332) - More reliably fail runs whose replay diverges from the event log. (#347) - Runs will now fail even in the case where the main thread of execution is not directly blocked on the suspension that is erroring. (#347) - Fixed workflow and step calls with both positional-or-keyword parameters and `*args` failing during replay because their arguments were recorded in an unbindable shape. (#312) Internal -------- - Remove a just-added return from a finally block. (#344) - Correct internal workflow type annotations found by checking untyped function bodies. (#337) - Refactored event replay. (#341) - Construct the protocol models by Python field name. (#322) vercel ------ 0.11.0 - 2026-08-31 ------------------- Features -------- - Expose `get_deadline()` for reading the current Function invocation deadline. (#306) - Answer workflow health checks for both queue-based transport and HTTP. (#292) - Add support to read the sealed (`encp`) workflow payloads (X25519 + AES-GCM) an outside writer addresses to a run, under the `encryption` extra. (#297) Bug Fixes --------- - Remove upper bounds on aggregate Sandbox and Workflow dependencies so sibling releases cannot make the `vercel` package un-installable. (#334) - Start a workflow run even when its queue message arrives before the `run_created` event has landed. (#284) Internal -------- - The Workflows implementation now ships in the separate `vercel-workflow` distribution, which `vercel` depends on, so `vercel.workflow` imports keep working without installing anything extra. (#299) vercel-apscheduler ------------------ 0.3.0 - 2026-08-31 ------------------ Breaking Changes ---------------- - The managed Redis backend was removed. The integration now always runs on its managed job store (Vercel Runtime Cache); a configured default `RedisJobStore` is rejected at import, `VERCEL_APSCHEDULER_BACKEND` accepts only `cache`, and the `redis` dependency is gone. The scheduler's durable identity now always derives from the builder-assigned subscriber id (previously the Redis `jobs_key`); the `scheduler_id` option still pins an identity explicitly. (#286) vercel-celery ------------- 0.7.5 - 2026-08-31 ------------------ - Update dependencies. vercel-django-tasks ------------------- 0.7.0 - 2026-08-31 ------------------ Features -------- - Add a Vercel Queues backend for Django Tasks and use it by default when no task backends are configured. (#291) vercel-dramatiq --------------- 0.7.4 - 2026-08-31 ------------------ - Update dependencies.
scotttrinh
added a commit
that referenced
this pull request
Sep 1, 2026
vercel-headers -------------- 0.7.2 - 2026-09-01 ------------------ Bug Fixes --------- - Accept request objects with concrete header implementations in the IP address and geolocation type annotations. (#337) vercel-internal-core -------------------- 0.1.3 - 2026-09-01 ------------------ Internal -------- - Support disabling HTTP timeouts for selected SDK operations while preserving the client default elsewhere. (#307) vercel-oidc ----------- 0.8.1 - 2026-09-01 ------------------ - Update dependencies. vercel-connect -------------- 0.1.1 - 2026-09-01 ------------------ - Update dependencies. vercel-internal-telemetry ------------------------- 0.7.3 - 2026-09-01 ------------------ - Update dependencies. vercel-queue ------------ 0.8.1 - 2026-09-01 ------------------ Bug Fixes --------- - Force embedded development servers to exit when graceful shutdown stalls. (#351) Documentation ------------- - Remove documentation and examples for `asgi_app` in preparation for its removal. (#309) vercel-sandbox -------------- 0.5.0 - 2026-09-01 ------------------ Features -------- - Add sync and async `fork_sandbox(...)` support for creating a sandbox from an existing named sandbox with optional configuration overrides. (#257) - Add `region` and `failover_regions` configuration for sandbox creation, forks, and updates, plus multi-region snapshot availability reporting. (#308) - Forward private ``__``-prefixed parameters to the Sandbox API. (#350) Bug Fixes --------- - Allow Sandbox process waits and log streams to remain idle longer than the session HTTP timeout. (#307) - Expose Linux process signals consistently on every SDK host platform. (#352) vercel-cache ------------ 0.7.3 - 2026-09-01 ------------------ - Update dependencies. vercel-workflow --------------- 0.10.0 - 2026-09-01 ------------------- Breaking Changes ---------------- - Make `await hook` never return `None` (#353) Raises a new `HookDisposedError` instead of returning `None` when the hook has been disposed. It is now typed to return `T` instead of `T | None`. `async for` over a hook will stop iterating on disposal, still. - Make sleep() and retry delays treat numbers as seconds, not ms (#346) This matches Python standard library APIs. - Use type annotations on workflows and step to allow passing Pydantic models and dataclasses. (#317) This is a breaking change, because type annotations will now be enforced. Passing a `dict` when the declaration expects a `list` will fail. Pydantic models and dataclasses can no longer be passed to `@serializable` or `register_serializable()`. Annotate the workflow or step parameter or return value with their type instead. Features -------- - Support `call_later`, `call_at`, and `now` in the event loop implementation. (#343) This enables use of `asyncio.sleep()` as well as `asyncio.timeout` and the `timeout` parameter of `asyncio.wait_for`. - Add opt-in cancellable steps: `@workflows.step(cancellable=True)`. When `cancel()` is called on a cancellable step, we send a message on a stream that the step will listen for. If it gets a message, it will exit. Note that like regular asyncio tasks, `cancel()` does not cause the step to immediately become "cancelled". Waiting on it will still wait for the step to actually terminate. If there are still cancellable steps running when a workflow function completes, they will be cancelled and the workflow will wait for them to finish before terminating. - `get_workflow_metadata()` returns the current run's `WorkflowInfo` (run id, workflow name, start time, deployment URL, and feature flags), callable from a workflow body or a step body — mirroring the JS SDK's `getWorkflowMetadata()`. (#320) One current limitation is that `started_at` is `None` from inside a step. - Make `HookEvent` an async context manager (#354) This matches TS, which supports `using`. ``` # disposes the hook on block exit async with SomeHook.wait(...) as hook: res = await hook ``` - Add `HookEvent.get_conflict()` to check for a token conflict without waiting for hook data. - `BaseHook.wait()` accepts `metadata` to record on the hook, and `get_hook_by_token()` reads it back for a resumer. (#301) - A step can raise `RetryableError` to control when its next attempt runs. (#302) - Accept `specVersion` 7 sealed noop event logs. (#319) - Failed run and step events now preserve serialized error classes, messages, stacks, and causes. Failed runs also expose a plaintext `errorCode`. (#304) - A workflow or step can attach plaintext metadata to its run with `set_attributes()`. (#303) - Add a `share_sandboxes` parameter to `SandboxPolicy` to enable reusing already created sandboxes instead of creating a new one on each invocation. This speeds up workflows but means that modifications to global state may persist between invocations. (#310) - Support `timedelta` arguments for workflow `sleep()` and retry delays. (#342) - Expose unstable API to serve workflow HTTP endpoint from your own web framework. (#294) - Added semi-internal manifest API for TS tools and e2e test. (#296) Bug Fixes --------- - Fix failing or even crashing cipher calls inside the workflow sandbox. (#305) - Fail a workflow run with `HookConflictError` when another run already owns its hook token instead of leaving it running indefinitely. (#327) - Fix a bug that caused reusing a hook token after disposing the previous hook to conflict with the same workflow run. - Support resuming hooks with payload in the queue message. (#300) - Prevent recursive workflow sandbox imports on Windows and decode Node CLI output as UTF-8. - Fix some bugs involving hooks arriving when the workflow was not yet blocked on them. (#339) - Fixed nulls rejected by server, requiring Pydantic 2.12 or newer. (#321) - Prevent workflows from having side effects while suspending. (#332) `hook.dispose()` will now work properly in a `finally` block. (That is, the hook will be disposed only when the workflow is actually terminating, and not every time it gets replayed.) - Fail an unregistered workflow step permanently and resume its workflow with a clear error instead of returning a `KeyError` and redelivering forever. - More reliably fail runs whose replay diverges from the event log. (#347) Runs will now fail even in the case where the main thread of execution is not directly blocked on the suspension that is erroring. - Fixed workflow and step calls with both positional-or-keyword parameters and `*args` failing during replay because their arguments were recorded in an unbindable shape. (#312) Internal -------- - Remove a just-added return from a finally block. (#344) - Correct internal workflow type annotations found by checking untyped function bodies. (#337) - Refactored event replay. (#341) - Construct the protocol models by Python field name. (#322) vercel ------ 0.11.0 - 2026-09-01 ------------------- Features -------- - Expose `get_deadline()` for reading the current Function invocation deadline. (#306) - Answer workflow health checks for both queue-based transport and HTTP. (#292) - Add support to read the sealed (`encp`) workflow payloads (X25519 + AES-GCM) an outside writer addresses to a run, under the `encryption` extra. (#297) Bug Fixes --------- - Remove upper bounds on aggregate Sandbox and Workflow dependencies so sibling releases cannot make the `vercel` package un-installable. (#334) - Start a workflow run even when its queue message arrives before the `run_created` event has landed. (#284) Internal -------- - The Workflows implementation now ships in the separate `vercel-workflow` distribution, which `vercel` depends on, so `vercel.workflow` imports keep working without installing anything extra. (#299) vercel-apscheduler ------------------ 0.3.0 - 2026-09-01 ------------------ Breaking Changes ---------------- - The managed Redis backend was removed. The integration now always runs on its managed job store (Vercel Runtime Cache); a configured default `RedisJobStore` is rejected at import, `VERCEL_APSCHEDULER_BACKEND` accepts only `cache`, and the `redis` dependency is gone. The scheduler's durable identity now always derives from the builder-assigned subscriber id (previously the Redis `jobs_key`); the `scheduler_id` option still pins an identity explicitly. (#286) vercel-celery ------------- 0.7.5 - 2026-09-01 ------------------ - Update dependencies. vercel-django-tasks ------------------- 0.7.0 - 2026-09-01 ------------------ Features -------- - Add a Vercel Queues backend for Django Tasks and use it by default when no task backends are configured. (#291) vercel-dramatiq --------------- 0.7.4 - 2026-09-01 ------------------ - Update dependencies.
This branch was successfully deployed
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.
Third of three, and the actual fix. Stacked on #283.
The bug
runtime.pyopenedworkflow_handlerwithworkflow_run = await world.runs_get(run_id). Sincestart()does not order itsrun_createdwrite against the queue push, a delivery can arrive before the run row exists — so that read 404s. The queue was not set to redeliver, due to added latency.Field evidence from the e2e Vercel lane: the 404 lands ~460ms after
start(), runtime-logs record exactly1 requestfor the run, and the driver waits out its 60s timeout. Roughly one arbitrary run per suite, on a different fixture each time — which reads as flakiness and is not. Three observed runs: two failed onsleepingWorkflow/promiseAllWorkflow, one passed becauserun_createdhappened to win.The fix
Write
run_startedfirst instead of reading. It transitions the run torunningand returns the run entity, so the read was a round-trip we never needed — and on a run whose row has not landed, it is the write that creates it from therunInputthe message carried. This is what the TypeScript runtime does; the run row is a cache, not a precondition.The creating client's
specVersionis stamped on the event so a run this path creates is not relabelled to ourSPEC_VERSION_CURRENT(2).Cross-environment guard
Resilient start creates the run under our tenant, so a message whose run was created in another environment would fork it: two copies of one run id, the creator's pending forever and ours running, with every cross-tenant queue ack failing to find its message.
refuse_cross_environment_deliverycompares the creator's environment (fromrunInput) against our own and discards the delivery before therun_startedwrite — refusing after it would be too late. It skips whenever either side is unknown, so the local world and older clients are unaffected.Without this, the fix would trade a loud 404 for a much harder-to-diagnose fork.
Test plan
17 new tests.
FakeWorld.runs_getraises outright, so any test that passes only because the handler read the run is failing by construction.Mutation-checked: restoring the pre-read fails 15 of 17; dropping
eventData, forcingSPEC_VERSION_CURRENT, skipping the guard, making the guard refuse on a match, widening theexcept, narrowing it to dropRunExpiredError, and dropping the cancelled check each fail at least one test.Two notes on coverage:
cancelledearly return looked redundant against the laterstatus != "running"check until I mutation-tested it; it is load-bearing only for a run cancelled before it started, which has nostartedAt. That case now has its own test.Closes the
resilient start: addTenWorkflow completes when run_created returns 500conformance gap — the deterministic version of this same defect, currently carried asunsupportedin the workbench app.