Make runtime tuning constants env-configurable; forward server limit-override header#2718
Make runtime tuning constants env-configurable; forward server limit-override header#2718VaguelySerious wants to merge 1 commit into
Conversation
…override header Adds `envNumber` (in @workflow/world) — a shared helper that resolves a numeric tuning constant from a `WORKFLOW_*` env var, clamps to an optional range, and falls back to the compiled-in default (warning once) on invalid input. Converts ~17 previously-hardcoded runtime constants to read through it: request/replay/wait timeouts, queue-delivery and retry counts, framed-stream reconnect caps, stream flush interval, body-parse and event-POST retry backoff, compression thresholds, memoization and lock-poll knobs. Also forwards `WORKFLOW_TEST_LIMIT_OVERRIDES` (a JSON object) verbatim as the `x-workflow-test-limit-overrides` request header, so a deployment can tighten the backend's own limits (stream max-duration, chunk-batch size) — the server validates and clamps it stricter-only. Together these let a dedicated e2e deployment dial limits down so the existing suite exercises edge paths (reconnect, batch splitting, retries) that otherwise only trigger after long durations or large payloads. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 99077e3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
🧪 E2E Test Results✅ All tests passed Summary
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
✅ 📋 Other
|
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 1 step💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 25 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 10 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 25 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 50 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 10 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) workflow with 25 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) workflow with 50 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) stream pipeline with 5 transform steps (1MB)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Express | Next.js (Turbopack) 10 parallel streams (1MB each)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) fan-out fan-in 10 streams (1MB each)💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Nitro | Next.js (Turbopack) SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
|
What
Two related changes that let a dedicated e2e deployment dial SDK + backend limits down so the existing suite exercises edge paths (stream reconnect, chunk-batch splitting, retries) that otherwise only trigger after long durations or large payloads.
1.
envNumberhelper + env-configurable constantsNew
envNumberin@workflow/world: resolves a numeric tuning constant from aWORKFLOW_*env var, clamps to an optional[min,max], and falls back to the compiled-in default (warning once) on invalid input — never throws. Reads lazily, mirroring the existinggetReplayTimeoutMs()pattern.Converts ~17 previously-hardcoded constants to read through it:
WORKFLOW_REQUEST_TIMEOUT_MSREQUEST_TIMEOUT_MSWORKFLOW_MAX_CHUNKS_PER_REQUESTMAX_CHUNKS_PER_REQUESTWORKFLOW_STREAM_FLUSH_INTERVAL_MSSTREAM_FLUSH_INTERVAL_MSWORKFLOW_FRAMED_STREAM_MAX_RECONNECTS/..._TOTAL_RECONNECTSWORKFLOW_MAX_QUEUE_DELIVERIESMAX_QUEUE_DELIVERIESWORKFLOW_REPLAY_TIMEOUT_MAX_RETRIES/WORKFLOW_REPLAY_DIVERGENCE_MAX_RETRIESWORKFLOW_WAIT_CONTINUATION_MAX_DELAY_SECONDS/WORKFLOW_NEAR_ELAPSED_WAIT_THRESHOLD_SECONDSWORKFLOW_MAX_EVENT_POST_RETRIES/WORKFLOW_EVENT_POST_RETRY_BASE_MS/..._JITTER_MSWORKFLOW_MAX_BODY_PARSE_RETRIES/WORKFLOW_BODY_PARSE_RETRY_BASE_MSWORKFLOW_COMPRESSION_MIN_BYTES/WORKFLOW_COMPRESSION_MIN_SAVINGS_RATIOWORKFLOW_MAX_MEMOIZED_PRIMITIVE_LENGTHWORKFLOW_DEFERRED_CHECK_DELAY_MS/WORKFLOW_LOCK_POLL_INTERVAL_MSEach keeps its exported
constas the documented default; only the resolution path changed.2. Forward server-side limit overrides
getHeaders(world-vercel) forwardsWORKFLOW_TEST_LIMIT_OVERRIDES(a JSON object of server-constant → value) verbatim as thex-workflow-test-limit-overridesrequest header. The server validates and clamps it stricter-only, so a malformed value is harmlessly ignored there — the client doesn't parse it. Unset in production. This is the client half of the server-side mechanism.Scope notes
Pure validation limits (
ATTRIBUTE_*, ULID timestamp thresholds) are intentionally left hardcoded — they aren't timing knobs and are enforced server-side.Tests
packages/world/src/env-config.test.ts: parse/clamp/integer/min/max/fallback/zero behavior.packages/world-vercel/src/utils.test.ts: header omitted when unset; forwarded verbatim when set.🤖 Generated with Claude Code