Skip to content

fix(effect): replace hardcoded Date.now() in FiberId.unsafeMake with configurable clock source#6167

Open
copyleftdev wants to merge 2 commits intoEffect-TS:mainfrom
copyleftdev:fix/fiberId-configurable-clock-source
Open

fix(effect): replace hardcoded Date.now() in FiberId.unsafeMake with configurable clock source#6167
copyleftdev wants to merge 2 commits intoEffect-TS:mainfrom
copyleftdev:fix/fiberId-configurable-clock-source

Conversation

@copyleftdev
Copy link
Copy Markdown

Problem

FiberId.unsafeMake() uses Date.now() for startTimeMillis, which feeds into Hash.symbol() and Equal.symbol():

// fiberId.ts:75
[Hash.symbol](): number {
  return Hash.cached(this, Hash.string(`${FiberIdSymbolKey}-${this._tag}-${this.id}-${this.startTimeMillis}`))
}

This means fiber identity hashing and equality are non-deterministic across runs. Two fibers created with the same counter ID but at different wall-clock times produce different hashes and are not equal.

This contributes to scheduler-related issues:

It also makes deterministic testing of the fiber runtime impossible without monkey-patching Date.now globally, which breaks timers, logging, and concurrent tests.

Fix

Replace the hardcoded Date.now() call with a globalValue-backed configurable clock source:

const _clockSource = globalValue(
  Symbol.for("effect/Fiber/Id/_clockSource"),
  (): { now: () => number } => ({ now: () => Date.now() })
)
  • Default behavior is identicalDate.now() is still called
  • setClockSource(fn) / resetClockSource() allow swapping for deterministic testing
  • No global mutation of Date.now
  • 1 file changed, 22 insertions, 1 deletion

Test plan

  • Fiber.test.ts — 16 tests pass
  • Effect/concurrency.test.ts — 24 tests pass
  • Effect/racing.test.ts — 4 tests pass
  • Zero regressions

🤖 Generated with Claude Code

…configurable clock source

FiberId.unsafeMake() uses Date.now() for startTimeMillis, which feeds
into Hash.symbol() and Equal.symbol() on the FiberId. This means fiber
identity hashing and equality are non-deterministic across runs — two
fibers created with the same counter ID but at different wall-clock
times produce different hashes.

This contributes to scheduler-related issues like Effect-TS#6124 (scheduler
runner isolation) and Effect-TS#6126 (MixedScheduler PROMISE leaks in vitest),
where fiber-keyed caches behave inconsistently due to timing-dependent
identity.

Replace with a globalValue-backed clock source that defaults to
Date.now() (zero behavior change) but can be swapped via
setClockSource()/resetClockSource() for deterministic testing without
monkey-patching Date.now globally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-project-automation github-project-automation bot moved this to Discussion Ongoing in PR Backlog Apr 12, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 12, 2026

🦋 Changeset detected

Latest commit: 377c9ef

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 36 packages
Name Type
effect Patch
@effect/cli Patch
@effect/cluster Patch
@effect/experimental Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/platform Patch
@effect/printer-ansi Patch
@effect/printer Patch
@effect/rpc Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-drizzle Patch
@effect/sql-kysely Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/sql Patch
@effect/typeclass Patch
@effect/vitest Patch
@effect/workflow Patch
@effect/ai Patch
@effect/ai-amazon-bedrock Patch
@effect/ai-anthropic Patch
@effect/ai-google Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch

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

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Discussion Ongoing

Development

Successfully merging this pull request may close these issues.

1 participant