[codex] Reproduce reused-sleep replay divergence in core runtime#2169
Draft
pranaygp wants to merge 3 commits into
Draft
[codex] Reproduce reused-sleep replay divergence in core runtime#2169pranaygp wants to merge 3 commits into
pranaygp wants to merge 3 commits into
Conversation
|
Contributor
Contributor
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests🌍 Community Worlds (69 failed)mongodb-dev (1 failed):
redis-dev (1 failed):
turso-dev (1 failed):
turso (66 failed):
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
❌ 🌍 Community Worlds
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
| expect(result).toEqual(['first', 'second']); | ||
| }); | ||
|
|
||
| it('should let a queued hook payload win when a reused wait completes after the step that installs the race', async () => { |
Contributor
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.
What this proves
This adds core-runtime regression and discriminator tests for the observed
Promise.race([iterator.next(), reused sleep])divergence. The tests drivesetupWorkflowContext()with an explicitly ordered in-memory event history, so they do not involve DynamoDB, Postgres,world-local, a Vercel deployment, or network timing.The ordered durable history is:
That history records the hook branch having won: the durable next operation is
drainStep. Currentstablereplay instead follows the sleep branch and attempts to consumesyncNextStep, reporting the same path-divergence corruption observed in hosted runs.Expected failing validation
The targeted suite deterministically fails for both late-waiter race expressions in both deserialization modes:
Promise.race([ iterator.next().then(value => ({ kind: "hook", value })), pendingSleep.then(() => ({ kind: "sleep" })), ]) Promise.race([iterator.next(), pendingSleep]) Corrupted event log: step event step_created ... belongs to "drainStep", but the current step consumer is "syncNextStep"As a positive control, the same history passes in both deserialization modes when the hook waiter exists before
setupStepcompletes:This PR is intentionally test-only and expected to be red. Its purpose is to demonstrate that the failure is in core replay behavior even when storage has already supplied a valid ordered event history, while identifying the subscription timing boundary.
Promise-shape discriminator
The raw
Promise.race([iterator.next(), pendingSleep])comparison fails with the samedrainStepversussyncNextStepdivergence as the mappedthen(...)comparison. I also ran a local exploratory direct-hook control,Promise.race([hook, pendingSleep]), and it fails the same way. Conversely, installingiterator.next()before awaitingsetupSteppasses.That rules out the additional result-mapping
.then(...)and the async iterator layer as the deciding cause for this event history. The sharper explanation is thathook_receivedis buffered before the post-setupStephook waiter exists; while thestep_completedpromise is queued for delivery,EventsConsumeradvances viaprocess.nextTick()and consumeswait_completed, queuing the reused sleep resolution before resumed workflow code has installed its next race. Pre-installing the waiter gives the buffered hook delivery an opportunity to be ordered correctly and makes replay deterministic for the recorded hook-winning path.Relationship to the candidate fix
#2048 contains the candidate runtime repair. The equivalent replay case passes on that branch, together with its handler-level stale-snapshot/delta replay tests. Keeping this PR separate provides a small failing control that can be cherry-picked or used while evaluating alternate fixes.