server: onMutationCommitted, a post-commit hook with net row changes — 0.2.1 - #1
Merged
Merged
Conversation
…— 0.2.1
WorkspaceEngineConfig gains onMutationCommitted(event, env), invoked once per
mutation that wrote rows, after its transaction committed, with { workspaceId,
name, args (parsed), principal, clientId, version, changes }. Each change is the
row's stored image at the mutation's first touch against what it left, so a row
put twice reports once and a create-then-delete of a new row reports nothing.
The hook observes and never participates: it is never awaited (the push handler
stays synchronous), a returned promise goes to waitUntil, and a throw or
rejection lands on the engine logger with the mutation name and version.
Migrations, admin import and reset bypass the mutation path and never fire it;
rejected mutations and no-op writes are silent too. Delivery is at-most-once.
Before-image capture is opt-in on the WriteSet and the DO enables it only when
a hook is configured, so apps without one pay nothing. A tx.get that reached
storage doubles as the image, so read-modify-write mutators add no read; blind
puts pay one point lookup. Migrations never track.
createTestEngine().mutate() returns the same changes list, so the logic behind a
hook is unit-testable in node. Additive API, hence a patch.
Claude-Session: https://claude.ai/code/session_012Xd62wDxf41DjJK1T3Wh3Y
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthroughAdds net row-change tracking to ChangesPost-commit mutation notifications
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant DurableObject
participant WriteSet
participant onMutationCommitted
participant waitUntil
participant logger
Client->>DurableObject: Submit mutation
DurableObject->>WriteSet: Flush candidate writes
WriteSet-->>DurableObject: Return written count and row changes
DurableObject->>onMutationCommitted: Invoke committed event
onMutationCommitted-->>DurableObject: Return synchronously or return promise
DurableObject->>waitUntil: Hold returned promise
onMutationCommitted-->>logger: Report throw or rejection
DurableObject-->>Client: Send mutation confirmation
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
InfinityBowman
added a commit
that referenced
this pull request
Sep 7, 2026
The convergence test polls mid-stream with 50ms waits and treats a timeout as "nothing pending". But a timed-out nextFrame left its waiter queued, so the next frame to arrive resolved a promise nobody awaited and never reached the queue — one relayed edit vanished per stale waiter, and the two docs diverged. It surfaced on a contended CI runner (PR #1's run, alongside the push run for the same commit), where relays arrive late enough to trip it. The harness now withdraws a waiter when its timer fires, for frames, JSON and close alike. The test also counts what each side is owed — every update one client sends is relayed to the other exactly once — and the final drain waits for that count with the normal timeout instead of reading silence as done, so a slow relay waits rather than fails. Claude-Session: https://claude.ai/code/session_012Xd62wDxf41DjJK1T3Wh3Y
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
WorkspaceEngineConfiggainsonMutationCommitted(event, env), invoked once per mutation that wrote rows, after its transaction committed, with{ workspaceId, name, args, principal, clientId, version, changes }. Each change is{ tbl, id, before, after }: the row's stored image at the mutation's first touch against what it left.waitUntil, throw or rejection lands on the engine logger with the mutation name and version.WriteSet; the DO enables it only when a hook is configured. Atx.getthat reached storage doubles as the image, so read-modify-write mutators add no read.createTestEngine().mutate()returns the samechangeslist for node-level testing of hook logic.Why
Three CoRATES issues want the same seam: assignment notifications (#628), D1 projections (#645), and workspace activity logging (#660). Built once to the #645 shape so none needs a further engine change.
Verification
commit-hook.test.ts, 5 node tests inwrite-changes.test.ts.pnpm typecheck,pnpm test(361 passing),pnpm check:packagesall green.Additive API, hence 0.2.1.
https://claude.ai/code/session_012Xd62wDxf41DjJK1T3Wh3Y
Summary by CodeRabbit
New Features
Documentation
Bug Fixes