mirror of
https://github.com/vercel/workflow.git
synced 2026-09-14 19:59:43 +08:00
feat(streams): add WebSocket capability gate (#3764)
## Summary & Motivation `WORKFLOW_STREAMS_TRANSPORT=ws` advertises client support for `workflow-stream-ws/v1` on stream writes; anything else keeps HTTP. It's a capability signal only — the server decides each upgrade, so there's no version or tenant-policy heuristic on the client side. ## Test Plan Unit tests for the gate's accepted values; typecheck, build, and lint pass locally.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@workflow/world-vercel': patch
|
||||
---
|
||||
|
||||
Add the default-off stream WebSocket capability gate.
|
||||
@@ -281,6 +281,14 @@ Platform-provided values such as `VERCEL_DEPLOYMENT_ID`, `VERCEL_PROJECT_ID`, an
|
||||
- Default: `1000`
|
||||
- Maximum stream chunks written in one Vercel World request. Larger batches are split.
|
||||
|
||||
### `WORKFLOW_STREAMS_TRANSPORT`
|
||||
|
||||
- Factory option: none
|
||||
- CLI flag: none
|
||||
- Default: `http`
|
||||
- Experimental stream-write transport capability. Set to exactly `ws` to advertise support for `workflow-stream-ws/v1` when it becomes available. The server authoritatively accepts or declines an upgrade; a decline uses HTTP directly. Stream reads remain HTTP and demand-driven.
|
||||
- This is not tenant rollout policy or a package-version check. HTTP remains the compatibility path. `/websockets/v1` is independent of REST v2/v4 and persisted workflow `specVersion` values.
|
||||
|
||||
### `WORKFLOW_DISABLE_ANALYTICS_READS`
|
||||
|
||||
- Factory option: none
|
||||
|
||||
@@ -200,6 +200,12 @@ Below the floor the deadline starts canceling requests that would have succeeded
|
||||
|
||||
Maximum stream chunks written in one Vercel World request. Larger batches are split across multiple requests. Default: `1000`. Minimum: `1`.
|
||||
|
||||
### `WORKFLOW_STREAMS_TRANSPORT`
|
||||
|
||||
Experimental stream-write transport capability. Default: `http`. Set `WORKFLOW_STREAMS_TRANSPORT=ws` to advertise support for `workflow-stream-ws/v1` when it becomes available. The server authoritatively accepts or declines every upgrade; a decline goes directly to HTTP. Reads remain HTTP and demand-driven.
|
||||
|
||||
This setting does not own tenant rollout policy and does not infer server support from package versions. HTTP remains the compatibility path. The protocol route (`/websockets/v1`) is versioned independently from REST v2/v4 and persisted workflow `specVersion` values. Drain/de-opt control semantics are a rollout prerequisite and are intentionally not part of this capability gate.
|
||||
|
||||
### `WORKFLOW_EVENTS_TRANSPORT`
|
||||
|
||||
Workflow run events ship to the Vercel World over a WebSocket instead of one HTTP request each. Default: `ws`.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { isWsStreamsTransportEnabled } from './ws-transport-enabled.js';
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env.WORKFLOW_STREAMS_TRANSPORT;
|
||||
});
|
||||
|
||||
describe('isWsStreamsTransportEnabled', () => {
|
||||
it.each([
|
||||
[undefined, false],
|
||||
['', false],
|
||||
['http', false],
|
||||
['HTTP', false],
|
||||
['ws ', false],
|
||||
['WS', false],
|
||||
['ws', true],
|
||||
])('advertises v1 only for the exact ws value: %j', (value, expected) => {
|
||||
if (value === undefined) {
|
||||
delete process.env.WORKFLOW_STREAMS_TRANSPORT;
|
||||
} else {
|
||||
process.env.WORKFLOW_STREAMS_TRANSPORT = value;
|
||||
}
|
||||
|
||||
expect(isWsStreamsTransportEnabled()).toBe(expected);
|
||||
});
|
||||
});
|
||||
@@ -53,3 +53,20 @@ export function isWsEventsTransportStrict(): boolean {
|
||||
const raw = process.env.WORKFLOW_INTERNAL_EVENTS_TRANSPORT_STRICT;
|
||||
return raw === '1' || raw === 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Advertise the experimental v1 stream-write protocol only when explicitly
|
||||
* requested. This is a client capability signal, not an entitlement: the
|
||||
* server authoritatively accepts or declines every upgrade, and a decline
|
||||
* falls back directly to the HTTP stream writer.
|
||||
*
|
||||
* HTTP is the compatibility path and the default. Unlike the default-on events
|
||||
* gate above, this opt-in is exact-match: a typo must fail toward HTTP rather
|
||||
* than unexpectedly enabling an experimental transport. This deliberately has
|
||||
* no package-version or tenant-policy heuristic; rollout policy belongs to the
|
||||
* server. v1 is `/websockets/v1`, independently versioned from REST v2/v4 and
|
||||
* persisted workflow spec versions.
|
||||
*/
|
||||
export function isWsStreamsTransportEnabled(): boolean {
|
||||
return process.env.WORKFLOW_STREAMS_TRANSPORT === 'ws';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user