Split wall and monotonic clock semantics - #6807
Conversation
🦋 Changeset detectedLatest commit: e620987 The changes in this PR will be included in the next version bump. This PR includes changesets to release 30 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 |
Bundle Size AnalysisGenerated from PR build output; treat the content below as untrusted.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Clock interface split:
currentTimeNanos*redefined as Unix wall-clock timestamps; newmonotonicTimeNanos*members added for elapsed duration measurement. JSDoc on both explicitly documents suitability and gotchas. - Wall-clock re-anchoring (
wallTimeNanos): Periodically (min 1s interval) re-computes the monotonic→wall origin when skew fromDate.now()exceeds 1 second, plus on wall-clock backward movement. Correctly handles both sudden and gradual drift. - Monotonic source selection:
process.hrtime.bigint()→performance.now()→ non-decreasingDate.now()fallback. The fallback'spreviousguard ensures it never decreases. - Duration migration:
Effect.timed,Effect.trackDuration, andSink.withDuration(and transitivelySink.timed) switch fromcurrentTimeNanosUnsafetomonotonicTimeNanosUnsafe. All tracing/log/metric timestamp call sites correctly remain on wall clock. - TestClock dual counters:
adjustand forwardsetTimeadvance both wall and monotonic; backwardsetTimeadvances only wall, preserving monotonic as a non-decreasing counter. Sleep deadlines advance monotonic to match. - Test coverage: Live-clock regression test with mocked
process.hrtime.bigint/Date.now, wall-backward duration tests fortimed/trackDuration/withDuration, TestClock counter tests for all adjustment scenarios, and OTel clock alignment test updated. - Changeset:
"effect": minorcorrectly flags the breaking change for customClockimplementors.
DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Removed skew-check rate limiting (
wallTimeNanos): EliminatedlastCheckMillis/checkIntervalMillisguard; skew vsDate.now()is now checked every call instead of at minimum 1s intervals. Fewer state variables, andDate.now()is cheap enough that the per-call check is harmless. - Simplified
Date.now()fallback: InitializedprevioustoBigInt(0)instead ofbigint | undefined, removing theundefinedbranch. The first call always sets it higher sinceDate.now()after epoch is always> 0. - Fixed floating-point precision in
advanceTo: ReplacedMath.floor(timestamp * 1e6) - Math.floor(currentTimestamp * 1e6)withMath.round(deltaMillis * 1_000_000). The old two-floorapproach could lose up to 1ns per term from floating-point truncation;Math.roundon the delta is exact for integer deltas and simpler. - Simplified live-clock regression test: Replaced
Effect.acquireUseReleasewithEffect.gen+Effect.ensuring— same assertions, far fewer indirections. - Added far-future precision test: Verifies
setTimeat timestamp1_000_000_000_000produces correct monotonic nanos withMath.round.
DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏

Type
Description
Fixes
Clock.currentTimeNanospermanently drifting from wall time when the runtime's monotonic clock pauses during host suspension or advances at a different rate fromDate.now().Previously, the live clock established its wall-clock origin once and never revisited it. This could leave nanosecond timestamps behind or ahead of Unix wall time for the lifetime of the process.
Changes
Clock.Clock:monotonicTimeNanosUnsafe()monotonicTimeNanosClock.monotonicTimeNanos.currentTimeMillisandcurrentTimeNanosas Unix-epoch wall-clock timestamps.process.hrtime.bigint()performance.now()Date.now()fallbackEffect.timedEffect.trackDurationSink.withDurationandSink.timedTestClockindependent wall and monotonic counters.effectminor changeset covering the required custom-Clockmigration.Tests
TestClockadjustment, forwardsetTime, backwardsetTime, and intermediate sleep deadlines.Local validation:
pnpm checkpassed.pnpm lintpassed.Related