feat: deterministic simulation testing (DST) framework#6216
Closed
copyleftdev wants to merge 4 commits intoEffect-TS:next-minorfrom
Closed
feat: deterministic simulation testing (DST) framework#6216copyleftdev wants to merge 4 commits intoEffect-TS:next-minorfrom
copyleftdev wants to merge 4 commits intoEffect-TS:next-minorfrom
Conversation
Ports the Deterministic Simulation Testing (DST) framework from the v3 branch: 1. fix(fiberId): replace hardcoded Date.now() with configurable clock source - Enables deterministic fiber identity for simulation testing - setClockSource() / resetClockSource() APIs - Original PR: Effect-TS#6167 2. feat(Scheduler): add stepOne() to ControlledScheduler - Execute exactly one task for fine-grained deterministic stepping - Prerequisite for DST scheduler - Original PR: Effect-TS#6168 3. feat(dst): full DST framework package - DSTScheduler: seeded PCG PRNG deterministic task scheduling - DSTRuntime: fully deterministic execution environment - LivenessChecker: post-hoc starvation/deadlock/infinite-loop detection - EventLog: structured execution trace for replay/debugging - V8Profiler: CPU profiling with source map resolution - GitBlame: commit attribution for hot code paths - CascadeExporter: NDJSON export for vajra analysis - CommitClassifier: conventional commit classification + fix-ratio scoring - ReportGenerator: HTML/JSON DST reports 4. feat(vitest): it.dst() test primitive - Multi-seed property-based concurrency testing - Automatic failure shrinking Co-authored-by: Don Johnson <dj@codetestcode.io>
Proves both issues are still present in v4 and validates the fixes: FiberId determinism: - BEFORE: Date.now() makes fiber hashes non-deterministic across runs - AFTER: configurable clock source → identical hashes given same seed - MUTATION: reverting clock source re-introduces non-determinism ControlledScheduler.stepOne(): - step() drains ALL tasks — no intermediate state observation - stepOne() executes exactly one task — enables DST stepping - Priority ordering verified - Returns false when no tasks pending Broader regression: 82 existing tests pass (Scheduler, FiberId, Fiber, FiberRef, concurrency)
🦋 Changeset detectedLatest commit: bde42b9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 37 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 |
Contributor
|
Effect v3 is under a feature freeze, feel free to move this contribution to the effect-smol repository. |
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.
Summary
Adds a deterministic simulation testing framework to Effect, enabling reproducible concurrency testing with seeded scheduling.
Changes
packages/effectScheduler.ts: addstepOne()toControlledScheduler— executes exactly one pending task, returnsbooleaninternal/fiberId.ts: replace hardcodedDate.now()inunsafeMake()with configurable clock source (setClockSource/resetClockSource)DSTScheduler.ts: public API for deterministic simulation —run(),runMany(), config typesinternal/dst/dstScheduler.ts: seeded PCG PRNG scheduler — same seed, same execution orderinternal/dst/dstRuntime.ts: assembles deterministic runtime (scheduler + clock + random)internal/dst/eventLog.ts: structured execution trace for replayinternal/dst/livenessChecker.ts: post-hoc starvation, deadlock, and infinite loop detectionpackages/vitestinternal/dst.ts:it.dst()test primitive for multi-seed property-based concurrency testingpackages/dstDSTRunner: multi-seed runner with optional V8 profiling and failure shrinkingV8Profiler: CPU profile capture with source map resolutionGitBlame: commit attribution for hot code pathsCascadeExporter: NDJSON export for external analysis toolingCommitClassifier: conventional commit classification and fix-ratio scoringReportGenerator: HTML/JSON DST reportsMotivation
ControlledScheduler.step()drains all pending tasks in a single call — there is no way to execute one task and observe intermediate state.FiberId.unsafeMake()usesDate.now(), making fiber identity non-deterministic across runs.Together, these prevent building FoundationDB/TigerBeetle-style deterministic simulation tests within Effect.
Prior work
stepOne()for ControlledSchedulerBoth issues are confirmed still present on current
mainafter the v4 merge.Tests
Checklist
pnpm buildonpackages/effect)