Harden event pagination responses#2180
Conversation
🦋 Changeset detectedLatest commit: 7ad78bb The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 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❌ Some tests failed Summary
❌ Failed Tests▲ Vercel Production (1 failed)vite (1 failed):
Details by Category❌ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
workflow with 1 step💻 Local Development
▲ Production (Vercel)
workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
workflow with 25 sequential steps💻 Local Development
▲ Production (Vercel)
workflow with 50 sequential steps💻 Local Development
▲ Production (Vercel)
Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.all with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
Promise.race with 50 concurrent steps💻 Local Development
▲ Production (Vercel)
workflow with 10 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 25 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 50 sequential data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 10 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 25 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
workflow with 50 concurrent data payload steps (10KB)💻 Local Development
▲ Production (Vercel)
Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
stream pipeline with 5 transform steps (1MB)💻 Local Development
▲ Production (Vercel)
10 parallel streams (1MB each)💻 Local Development
▲ Production (Vercel)
fan-out fan-in 10 streams (1MB each)💻 Local Development
▲ Production (Vercel)
SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
❌ Some benchmark jobs failed:
Check the workflow run for details. |
There was a problem hiding this comment.
Pull request overview
This PR hardens runtime event-log pagination so clients can tolerate rejected or overlapping cursors without replaying duplicate events or looping indefinitely.
Changes:
- Adds pagination guard helpers for cursor progress validation, deduplication, and one-time retry after rejected continuation cursors.
- Adds tests covering overlapping pages, rejected cursors, repeated cursors, and missing cursors with
hasMore. - Fixes incremental event merges to update the local
existingIdsset while appending.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
packages/core/src/runtime/helpers.ts |
Adds event pagination deduplication, cursor retry, and contract-error guards. |
packages/core/src/runtime/helpers.test.ts |
Adds regression tests for hardened pagination behavior. |
packages/core/src/runtime.ts |
Prevents duplicate IDs during incremental runtime event merges. |
.changeset/calm-events-guard.md |
Records a patch release note for the runtime pagination hardening. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
VaguelySerious
left a comment
There was a problem hiding this comment.
See review on #2179, please address the same nits
|
No backport to The To override, re-run the Backport to stable workflow manually via |
Summary
Why
This is client-side defense in depth for the cursor compatibility issue addressed by vercel/workflow-server#454. Older or partially migrated server behavior can reject a cursor, ignore it, or restart a continuation read at the beginning of the log. The runtime should not replay duplicated events or loop indefinitely when that happens.
The server still needs to preserve legacy cursor compatibility for clients that have already shipped. These guards make newly released clients more tolerant of rejected or overlapping reads and more explicit about malformed pagination responses.
Validation
pnpm --filter '@workflow/core...' buildpnpm --filter @workflow/core typecheckpnpm --filter @workflow/core test(1080tests passed)pnpm exec biome check packages/core/src/runtime/helpers.ts packages/core/src/runtime/helpers.test.ts .changeset/calm-events-guard.mdgit diff --check