Repository navigation
Add WebSocket transport for step-execution event writes (opt-in) #3084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c9a2f11
9944538
48ce01c
4652406
bba29bc
e2d42c6
782654b
254a1e7
c8b6cd9
56bac0a
1e9418b
93da2b7
e455eb5
98978cc
ca72293
9dc3cd3
4690bd5
8fb9d9b
b8f521e
a147706
1228472
0b8d9bb
fb55e86
f9aa924
fe80ddb
5032530
c67d974
f0f9b8d
fabd095
f7ecda8
db919d0
d39c325
32bbb3a
6694cdf
df8dc38
95d6799
99db44b
adcbc4b
07cdfc0
d984235
0e89321
271a564
4ac2557
79f2860
ad29424
57b6177
b3ee568
0b62e6b
178a005
2bf2c1f
368c266
9e5ecdb
b4c1d7f
4921cef
c2f94eb
d9c934f
a800f82
256a1c6
27811ea
2a8d8c3
37a5e8f
34ac1e9
b3ccab7
be15f05
6607983
e8f1d66
d1b3581
9bffb4b
edc10df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| '@workflow/world-vercel': minor | ||
| '@workflow/builders': patch | ||
| '@workflow/rollup': patch | ||
| '@workflow/next': patch | ||
| --- | ||
|
|
||
| Add an opt-in WebSocket transport for event writes during step execution, enabled with `WORKFLOW_EVENTS_TRANSPORT=ws`. Defaults to HTTP; no behavior change unless explicitly enabled. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -604,6 +604,185 @@ jobs: | |||||||||||||||||||
| retention-days: 7 | ||||||||||||||||||||
| if-no-files-found: ignore | ||||||||||||||||||||
|
|
||||||||||||||||||||
| e2e-vercel-ws-transport: | ||||||||||||||||||||
| # Dedicated coverage for world-vercel's WebSocket events transport | ||||||||||||||||||||
| # (WORKFLOW_EVENTS_TRANSPORT=ws — see events-v4.ts's | ||||||||||||||||||||
| # isWsEventsTransportEnabled). Every other job in this file exercises | ||||||||||||||||||||
| # the default HTTP transport only, now that the WS-on-by-default POC | ||||||||||||||||||||
| # hack is gone. | ||||||||||||||||||||
| # | ||||||||||||||||||||
| # Mirrors e2e-vercel-prod's shape (same apps subset, same full e2e | ||||||||||||||||||||
| # suite) but deploys itself via a plain `vercel deploy` (no | ||||||||||||||||||||
| # `--prebuilt`) instead of waiting for the GitHub App's passive | ||||||||||||||||||||
| # deployment — that's the only way to get a *second*, independent | ||||||||||||||||||||
| # deployment of a project we don't own the Environment Variables UI | ||||||||||||||||||||
| # for, with its own env var, without creating a whole new project. | ||||||||||||||||||||
| # | ||||||||||||||||||||
| # Deliberately NOT `--prebuilt`: an earlier version of this job built | ||||||||||||||||||||
| # locally on the runner via `vercel build --prebuilt` and hit a string | ||||||||||||||||||||
| # of environment-specific bugs that don't reproduce on a real | ||||||||||||||||||||
| # deployment (missing `serverExternalPackages` tracing for | ||||||||||||||||||||
| # `@workflow/world-vercel`, nitro preset auto-detection picking | ||||||||||||||||||||
| # `node-server` instead of `vercel`, needing the whole monorepo | ||||||||||||||||||||
| # pre-built on this runner). Plain `vercel deploy` uploads source and | ||||||||||||||||||||
| # builds remotely on Vercel's own infra — the exact same pipeline the | ||||||||||||||||||||
| # GitHub App uses for e2e-vercel-prod's deployments — so none of that | ||||||||||||||||||||
| # applies here. | ||||||||||||||||||||
| # Opt-in on PRs, unconditional on main. Three real `vercel deploy`s per | ||||||||||||||||||||
| # run is too much to charge every unrelated PR in the repo for a transport | ||||||||||||||||||||
| # that is off by default; main still gets the signal on every commit. | ||||||||||||||||||||
| # `workflow-server-test` counts as opt-in too — that label exists to test | ||||||||||||||||||||
| # workflow-server changes, which is where the WS protocol lives. | ||||||||||||||||||||
| # | ||||||||||||||||||||
| # `on.pull_request.types` has no `labeled`, so a label added to an already | ||||||||||||||||||||
| # open PR takes effect on the next push, not immediately. | ||||||||||||||||||||
| name: E2E Vercel WS Transport Test (${{ matrix.app.name }}) | ||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||
| timeout-minutes: 30 | ||||||||||||||||||||
| needs: ci-scope | ||||||||||||||||||||
| if: >- | ||||||||||||||||||||
| ${{ needs.ci-scope.outputs.fast-path != 'true' | ||||||||||||||||||||
| && (github.event_name != 'pull_request' | ||||||||||||||||||||
| || contains(github.event.pull_request.labels.*.name, 'ws-transport-test') | ||||||||||||||||||||
| || contains(github.event.pull_request.labels.*.name, 'workflow-server-test')) }} | ||||||||||||||||||||
| permissions: | ||||||||||||||||||||
| id-token: write | ||||||||||||||||||||
| contents: read | ||||||||||||||||||||
| strategy: | ||||||||||||||||||||
| fail-fast: false | ||||||||||||||||||||
| matrix: | ||||||||||||||||||||
| app: | ||||||||||||||||||||
| - name: "example" | ||||||||||||||||||||
| project-id: "prj_xWq20Dd860HHAfzMjK2Mb6TPVxMa" | ||||||||||||||||||||
| project-slug: "example-workflow" | ||||||||||||||||||||
| - name: "nextjs-turbopack" | ||||||||||||||||||||
| project-id: "prj_yjkM7UdHliv8bfxZ1sMJQf1pMpdi" | ||||||||||||||||||||
| project-slug: "example-nextjs-workflow-turbopack" | ||||||||||||||||||||
| - name: "express" | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AI Review: BlockingThis lane covers I checked the Rollup claim empirically. Adding a kill switch to const __viteOptionalPeerDep_bufferutil_ws_true = {};That object does not throw, so
So pre-fix this is total WS breakage on the Rollup family, and every CBOR event payload clears 48 bytes. Two consequences:
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed the claim and rationale. |
||||||||||||||||||||
| project-id: "prj_cCZjpBy92VRbKHHbarDMhOHtkuIr" | ||||||||||||||||||||
| project-slug: "workbench-express-workflow" | ||||||||||||||||||||
| # Vite resolves `ws`'s absent optional accelerators to a stub | ||||||||||||||||||||
| # instead of failing the require, so a build check can't see the | ||||||||||||||||||||
| # breakage and only a masked frame at or above 48 bytes trips it | ||||||||||||||||||||
| # (see WORKFLOW_OPTIONAL_WS_NATIVE_MODULES). Every CBOR event | ||||||||||||||||||||
| # frame clears that, so this lane is the coverage for it. | ||||||||||||||||||||
| - name: "vite" | ||||||||||||||||||||
| project-id: "prj_uLIcNZNDmETulAvj5h0IcDHi5432" | ||||||||||||||||||||
| project-slug: "workbench-vite-workflow" | ||||||||||||||||||||
| env: | ||||||||||||||||||||
| TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} | ||||||||||||||||||||
| TURBO_TEAM: ${{ vars.TURBO_TEAM }} | ||||||||||||||||||||
| WORKFLOW_PUBLIC_MANIFEST: '1' | ||||||||||||||||||||
| WS_TEAM_ID: "team_nO2mCG4W8IxPIeKoSsqwAxxB" | ||||||||||||||||||||
| steps: | ||||||||||||||||||||
| - name: Checkout Repo | ||||||||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||||||||
| with: | ||||||||||||||||||||
| ref: ${{ github.event.pull_request.head.sha || github.sha }} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Setup environment | ||||||||||||||||||||
| uses: ./.github/actions/setup-workflow-dev | ||||||||||||||||||||
| with: | ||||||||||||||||||||
| build-packages: 'false' | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Build CLI | ||||||||||||||||||||
| run: pnpm turbo run build --filter='@workflow/cli' | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # Pinned and installed once rather than `npx vercel@<version>` per | ||||||||||||||||||||
| # command — repeated `npx` resolution showed inconsistent behavior | ||||||||||||||||||||
| # (different Node version in the CLI's own banner, a doubled project | ||||||||||||||||||||
| # path) across otherwise-identical earlier CI attempts. | ||||||||||||||||||||
| - name: Install vercel CLI | ||||||||||||||||||||
| run: npm install -g vercel@56.2.0 | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Deploy a dedicated WS-transport preview | ||||||||||||||||||||
| id: wsDeploy | ||||||||||||||||||||
| env: | ||||||||||||||||||||
| WS_VERCEL_TOKEN: ${{ secrets.VERCEL_LABS_TOKEN }} | ||||||||||||||||||||
| run: | | ||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||
| # `vercel deploy` (source-upload mode, no --prebuilt) re-applies | ||||||||||||||||||||
| # the linked project's own Root Directory setting internally — | ||||||||||||||||||||
| # unlike `vercel build`, it expects to run from the repo root and | ||||||||||||||||||||
| # narrow down itself, the same way the GitHub App's own deploy | ||||||||||||||||||||
| # does. Passing `--cwd=<app dir>` here double-joins that Root | ||||||||||||||||||||
| # Directory underneath itself ("workbench/x/workbench/x does not | ||||||||||||||||||||
| # exist"). Link and deploy from the repo root — no --cwd at all — | ||||||||||||||||||||
| # and let the project's own Root Directory setting do the | ||||||||||||||||||||
| # narrowing, matching how every passively-triggered deployment in | ||||||||||||||||||||
| # this file already works. | ||||||||||||||||||||
| vercel pull --yes --environment=preview \ | ||||||||||||||||||||
| --project="${{ matrix.app.project-id }}" \ | ||||||||||||||||||||
| --scope="$WS_TEAM_ID" --token="$WS_VERCEL_TOKEN" | ||||||||||||||||||||
| # `vercel deploy` writes the new deployment's URL to stdout and | ||||||||||||||||||||
| # progress/logs to stderr, specifically so it composes as | ||||||||||||||||||||
| # `url=$(vercel deploy ...)` in scripts — do not redirect stderr | ||||||||||||||||||||
| # into this capture. `--target=preview` is explicit here even | ||||||||||||||||||||
| # though it's the default without `--prod` — these are shared, | ||||||||||||||||||||
| # production-adjacent projects, and this shouldn't ever silently | ||||||||||||||||||||
| # start deploying to their production aliases if a future edit | ||||||||||||||||||||
| # changes flags around this call. | ||||||||||||||||||||
| URL=$(vercel deploy --yes --target=preview \ | ||||||||||||||||||||
| -e WORKFLOW_EVENTS_TRANSPORT=ws \ | ||||||||||||||||||||
| --scope="$WS_TEAM_ID" --token="$WS_VERCEL_TOKEN") | ||||||||||||||||||||
| echo "url=$URL" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||
| # Best-effort: only used by the runtime-logs capture on failure, | ||||||||||||||||||||
| # which already skips gracefully if this doesn't parse. | ||||||||||||||||||||
| DEPLOYMENT_ID=$(vercel inspect "$URL" --format=json \ | ||||||||||||||||||||
| --scope="$WS_TEAM_ID" --token="$WS_VERCEL_TOKEN" 2>/dev/null \ | ||||||||||||||||||||
| | node -e "let d='';process.stdin.on('data',c=>d+=c).on('end',()=>{try{console.log(JSON.parse(d).id||'')}catch{}})" || true) | ||||||||||||||||||||
| echo "deploymentId=$DEPLOYMENT_ID" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Record E2E start time | ||||||||||||||||||||
| id: e2eStart | ||||||||||||||||||||
| run: echo "ms=$(($(date +%s) * 1000))" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Run E2E Tests | ||||||||||||||||||||
| run: pnpm run test:e2e --reporter=verbose --reporter=json --reporter=./packages/core/e2e/github-reporter.ts "--outputFile=e2e-vercel-ws-transport-$APP_NAME.json" | ||||||||||||||||||||
| env: | ||||||||||||||||||||
| NODE_OPTIONS: "--enable-source-maps" | ||||||||||||||||||||
| DEPLOYMENT_URL: ${{ steps.wsDeploy.outputs.url }} | ||||||||||||||||||||
| VERCEL_DEPLOYMENT_ID: ${{ steps.wsDeploy.outputs.deploymentId }} | ||||||||||||||||||||
| APP_NAME: ${{ matrix.app.name }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_ENV: "preview" | ||||||||||||||||||||
| WORKFLOW_VERCEL_AUTH_TOKEN: ${{ secrets.VERCEL_LABS_TOKEN }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_TEAM: ${{ env.WS_TEAM_ID }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_PROJECT: ${{ matrix.app.project-id }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_PROJECT_SLUG: ${{ matrix.app.project-slug }} | ||||||||||||||||||||
| VERCEL_WORKFLOW_SERVER_URL: ${{ github.ref != 'refs/heads/main' && secrets.VERCEL_WORKFLOW_SERVER_URL || '' }} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Capture runtime logs on failure | ||||||||||||||||||||
| if: failure() | ||||||||||||||||||||
| env: | ||||||||||||||||||||
| APP_NAME: ${{ matrix.app.name }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_AUTH_TOKEN: ${{ secrets.VERCEL_LABS_TOKEN }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_TEAM: ${{ env.WS_TEAM_ID }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_PROJECT: ${{ matrix.app.project-id }} | ||||||||||||||||||||
| WORKFLOW_VERCEL_ENV: "preview" | ||||||||||||||||||||
| VERCEL_DEPLOYMENT_ID: ${{ steps.wsDeploy.outputs.deploymentId }} | ||||||||||||||||||||
| E2E_START_MS: ${{ steps.e2eStart.outputs.ms }} | ||||||||||||||||||||
| run: node .github/scripts/fetch-e2e-runtime-logs.mjs | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Generate E2E summary | ||||||||||||||||||||
| if: always() | ||||||||||||||||||||
| env: | ||||||||||||||||||||
| APP_NAME: ${{ matrix.app.name }} | ||||||||||||||||||||
| run: node .github/scripts/aggregate-e2e-results.js . --job-name "E2E Vercel WS Transport ($APP_NAME)" >> $GITHUB_STEP_SUMMARY || true | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - name: Upload E2E results | ||||||||||||||||||||
| if: always() | ||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||
| with: | ||||||||||||||||||||
| name: e2e-results-vercel-ws-transport-${{ matrix.app.name }} | ||||||||||||||||||||
| path: | | ||||||||||||||||||||
| e2e-vercel-ws-transport-${{ matrix.app.name }}.json | ||||||||||||||||||||
| e2e-metadata-${{ matrix.app.name }}-vercel.json | ||||||||||||||||||||
| e2e-failures-${{ matrix.app.name }}-vercel.json | ||||||||||||||||||||
| e2e-diagnostics-${{ matrix.app.name }}-vercel.json | ||||||||||||||||||||
| e2e-runtime-logs-${{ matrix.app.name }}-vercel.json | ||||||||||||||||||||
| retention-days: 7 | ||||||||||||||||||||
| if-no-files-found: ignore | ||||||||||||||||||||
|
|
||||||||||||||||||||
| getTestMatrix: | ||||||||||||||||||||
| name: Get Test Matrix | ||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||
|
|
@@ -1129,7 +1308,7 @@ jobs: | |||||||||||||||||||
| summary: | ||||||||||||||||||||
| name: E2E Summary | ||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||
| needs: [ci-scope, e2e-vercel-prod, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-windows] | ||||||||||||||||||||
| needs: [ci-scope, e2e-vercel-prod, e2e-vercel-ws-transport, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-windows] | ||||||||||||||||||||
| if: always() && !cancelled() && needs.ci-scope.outputs.fast-path != 'true' | ||||||||||||||||||||
| timeout-minutes: 10 | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1165,7 +1344,7 @@ jobs: | |||||||||||||||||||
| e2e-required-check: | ||||||||||||||||||||
| name: E2E Required Check | ||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||
| needs: [ci-scope, unit, e2e-package-build, e2e-vercel-prod, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-windows] | ||||||||||||||||||||
| needs: [ci-scope, unit, e2e-package-build, e2e-vercel-prod, e2e-vercel-ws-transport, e2e-local-dev, e2e-local-prod, e2e-local-postgres, e2e-windows] | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AI Review: Note This adds three live
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now 4 new lanes. Gated on a new label |
||||||||||||||||||||
| if: always() | ||||||||||||||||||||
| timeout-minutes: 5 | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1175,13 +1354,20 @@ jobs: | |||||||||||||||||||
| UNIT_STATUS: ${{ needs.unit.result }} | ||||||||||||||||||||
| BUILD_STATUS: ${{ needs.e2e-package-build.result }} | ||||||||||||||||||||
| VERCEL_STATUS: ${{ needs.e2e-vercel-prod.result }} | ||||||||||||||||||||
| VERCEL_WS_STATUS: ${{ needs.e2e-vercel-ws-transport.result }} | ||||||||||||||||||||
| LOCAL_DEV_STATUS: ${{ needs.e2e-local-dev.result }} | ||||||||||||||||||||
| LOCAL_PROD_STATUS: ${{ needs.e2e-local-prod.result }} | ||||||||||||||||||||
| POSTGRES_STATUS: ${{ needs.e2e-local-postgres.result }} | ||||||||||||||||||||
| WINDOWS_STATUS: ${{ needs.e2e-windows.result }} | ||||||||||||||||||||
| FAST_PATH: ${{ needs.ci-scope.outputs.fast-path }} | ||||||||||||||||||||
| VALIDATION_FAST_PATH: ${{ needs.ci-scope.outputs.validation-fast-path }} | ||||||||||||||||||||
| HAS_LABEL: ${{ contains(github.event.pull_request.labels.*.name, 'workflow-server-test') }} | ||||||||||||||||||||
| # e2e-vercel-ws-transport runs on main and on labelled PRs only, so | ||||||||||||||||||||
| # its status is required in exactly those cases and must be allowed | ||||||||||||||||||||
| # to be `skipped` otherwise. | ||||||||||||||||||||
| WS_REQUIRED: ${{ github.event_name != 'pull_request' | ||||||||||||||||||||
| || contains(github.event.pull_request.labels.*.name, 'ws-transport-test') | ||||||||||||||||||||
| || contains(github.event.pull_request.labels.*.name, 'workflow-server-test') }} | ||||||||||||||||||||
| run: | | ||||||||||||||||||||
| FAILED_JOBS=() | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1199,6 +1385,9 @@ jobs: | |||||||||||||||||||
| if [[ "$HAS_LABEL" == "true" ]]; then | ||||||||||||||||||||
| echo "workflow-server-test label detected - only checking required jobs" | ||||||||||||||||||||
| [[ "$VERCEL_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-prod ($VERCEL_STATUS)") | ||||||||||||||||||||
| # This label is itself opt-in for the WS lane (see that job's `if`), | ||||||||||||||||||||
| # so it runs here and is required. | ||||||||||||||||||||
| [[ "$VERCEL_WS_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-ws-transport ($VERCEL_WS_STATUS)") | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # Verify other jobs were actually skipped | ||||||||||||||||||||
| [[ "$UNIT_STATUS" == "skipped" ]] || echo "Warning: unit was not skipped ($UNIT_STATUS)" | ||||||||||||||||||||
|
|
@@ -1211,6 +1400,11 @@ jobs: | |||||||||||||||||||
| [[ "$UNIT_STATUS" == "success" ]] || FAILED_JOBS+=("unit ($UNIT_STATUS)") | ||||||||||||||||||||
| [[ "$BUILD_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-package-build ($BUILD_STATUS)") | ||||||||||||||||||||
| [[ "$VERCEL_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-prod ($VERCEL_STATUS)") | ||||||||||||||||||||
| if [[ "$WS_REQUIRED" == "true" ]]; then | ||||||||||||||||||||
| [[ "$VERCEL_WS_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-vercel-ws-transport ($VERCEL_WS_STATUS)") | ||||||||||||||||||||
| else | ||||||||||||||||||||
| [[ "$VERCEL_WS_STATUS" == "skipped" ]] || echo "Warning: e2e-vercel-ws-transport ran unlabelled ($VERCEL_WS_STATUS)" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| [[ "$LOCAL_DEV_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-local-dev ($LOCAL_DEV_STATUS)") | ||||||||||||||||||||
| [[ "$LOCAL_PROD_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-local-prod ($LOCAL_PROD_STATUS)") | ||||||||||||||||||||
| [[ "$POSTGRES_STATUS" == "success" ]] || FAILED_JOBS+=("e2e-local-postgres ($POSTGRES_STATUS)") | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /** | ||
| * `bufferutil` and `utf-8-validate` are optional native accelerators for the | ||
| * `ws` package, which `@workflow/world-vercel` uses for its WebSocket events | ||
| * transport. Neither is installed by default: `ws` requires each one inside a | ||
| * try/catch and falls back to a pure-JS implementation when the require throws. | ||
| * | ||
| * Marking them external keeps that fallback reachable. Two bundlers take it away | ||
| * without changing the build's outcome, so the damage only shows up at runtime, | ||
| * on the first frame big enough to reach the native masker (`ws` uses pure JS | ||
| * below 48 bytes — small-payload smoke tests pass; CBOR event frames don't): | ||
| * | ||
| * - **webpack** bundles the JS wrapper without its native `.node` binding. | ||
| * - **Vite** resolves the absent peer to its own `optional-peer-dep` stub, so | ||
| * `ws`'s require *succeeds* and the try/catch never fires. | ||
| * | ||
| * Both end at `bufferUtil.mask is not a function`. Rollup-family setups are not | ||
| * known to break: nothing substitutes a stub, and nitro traces and externalizes | ||
| * `ws` in a production build, so the require stays a real one that fails and the | ||
| * fallback engages. Externalizing there buys determinism against a change in | ||
| * externals policy, not a fix for a known break. (Turbopack already externalizes | ||
| * Node packages.) | ||
| * | ||
| * Externalized unconditionally, unlike `WORKFLOW_OPTIONAL_OTEL_API_MODULE`, | ||
| * which is only externalized when it can't be resolved. The OTEL API has to | ||
| * load for tracing to work, so a self-contained output must bundle it when | ||
| * present; these accelerators must specifically *not* load, so a failed runtime | ||
| * require is the designed path and a half-bundled native module is not. | ||
| */ | ||
| export const WORKFLOW_OPTIONAL_WS_NATIVE_MODULES = [ | ||
| 'bufferutil', | ||
| 'utf-8-validate', | ||
| ] as const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AI Review: Note
There is no latency measurement for the WS path anywhere in the PR, even though latency is the motivation.
benchmarks.ymlnever setsWORKFLOW_EVENTS_TRANSPORTand waits on the passive deployment, so the benchmark referenced in the Testing section is measuring HTTP. Since this job already stands up its own deployment with the flag set, it is the cheapest place to capture a before/after number worth deciding the default on.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dropping a durabench screenshot here for reference. This force enabled websockets so there is promise. Shows consistent STSO p75 drop.