TS client: injectable currentTimestampProvider for reducer modifiedAt (#186)#189
Open
joshmouch wants to merge 1 commit into
Open
TS client: injectable currentTimestampProvider for reducer modifiedAt (#186)#189joshmouch wants to merge 1 commit into
joshmouch wants to merge 1 commit into
Conversation
…edAt (microsoft#186) The session reducer stamps summary.modifiedAt from the ambient wall clock (Date.now), which makes an identical (state, action) pair produce different output depending on when it runs — at odds with the documented 'pure reducers / same code on server and client' model. The Go, Kotlin, and Rust clients already expose an injectable now-seam for exactly this (Go SetNowProvider, Kotlin currentTimestampProvider, Rust MOCK_NOW_MS); the TypeScript client was the only one forcing consumers to monkeypatch the process-global Date.now. This adds a non-breaking, default-Date.now currentTimestampProvider + setCurrentTimestampProvider to the session reducer (mirroring Kotlin's name), re-exported through reducers.ts + index.ts, and replaces the 10 inline Date.now() sites with currentTimestampProvider(). The TS fixture test now injects the seam instead of monkeypatching the global Date.now (racy under concurrency), matching the other clients' fixture runners. typecheck clean; all 169 reducer tests pass (incl. the 163 shared fixtures). Refs: microsoft#186 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Author
|
@microsoft-github-policy-service agree |
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
Brings the TypeScript client to parity with Go/Kotlin/Rust by adding an injectable now-seam for the
summary.modifiedAttimestamps the session reducer stamps. Closes the TS half of #186.The problem (#186)
The docs state reducers are pure and "the same reducer code runs on both server and client, which is what makes write-ahead possible" — but
types/channels-session/reducer.tsstampssummary.modifiedAt = Date.now()at 10 sites, so an identical(state, action)pair yields different output depending on when it runs. Under write-ahead reconciliation the client replays the same action and stamps a differentmodifiedAtthan the server, until the server echo overwrites it.The Go, Kotlin, and Rust clients already deliberately stamp from a clock but expose an injectable seam for deterministic replay/tests (Go
SetNowProvider, KotlincurrentTimestampProvider, RustMOCK_NOW_MS). The TS client was the only one with no seam, forcing its own fixture test to monkeypatch the process-globalDate.now(racy under concurrency, not per-call controllable).The change (non-breaking)
types/channels-session/reducer.ts: addcurrentTimestampProvider: () => number(defaultDate.now) +setCurrentTimestampProvider(...), mirroring Kotlin'scurrentTimestampProvider. Replace the 10 inlineDate.now()sites withcurrentTimestampProvider().types/reducers.tsandtypes/index.ts.types/reducers.test.ts: inject the seam (setCurrentTimestampProvider(() => 9999)) inbeforeEachinstead of monkeypatching the globalDate.now— matching the other clients' fixture runners.Default behavior is unchanged (
Date.now), so this is purely additive for existing consumers.Verification
tsc --noEmit -p types/tsconfig.json— clean.tsx --test types/reducers.test.ts— 169 pass / 0 fail (incl. the 163 shared reducer fixtures, now driven through the seam).Note on intent
Filed issue-first as #186, which asked whether you'd prefer (a) docs clarification, (b) TS now-seam parity, or (c) a wire-breaking timestamp change. This PR implements (b) — the non-breaking option that matches the existing cross-client precedent — but happy to adjust toward (a)/(c) or a different seam name/shape per your preference.