Repository navigation
feat(bindings_node): expose the app data change callback and update guard - #4013
Conversation
|
Claude finished @tylerhawkes's task —— View job Code ReviewReview Date: 2026-08-19 20:04 UTC Overall, this is a well-structured implementation that correctly exposes the app data change callback to Node.js bindings. The code quality is high and follows established patterns. I have a few minor observations: Observations
SummaryThe implementation correctly handles the async callback contract, properly converts types at the FFI boundary (hex-encoding |
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces a new feature: app_data change callbacks and a compare-and-swap guard mechanism. It adds new callback infrastructure across multiple platforms (core, mobile, node, Android), a new intent state (Superseded), new error handling, and modifies sync/publish logic. Despite full code ownership by the author, new features with this scope warrant human review. This assessment was made without Macroscope's correctness findings, which could not be posted. Not approved because:
You can add or adjust custom eligibility rules. Learn more. |
6f021d2 to
b76a2e4
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4013 +/- ##
=======================================
Coverage 85.88% 85.88%
=======================================
Files 419 419
Lines 68348 68348
=======================================
Hits 58700 58700
Misses 9648 9648 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Dismissing prior approval to re-evaluate b76a2e4
b76a2e4 to
ac76516
Compare
ac76516 to
342b782
Compare
342b782 to
615d16b
Compare
Dismissing prior approval to re-evaluate 615d16b
615d16b to
bec4f9c
Compare
Dismissing prior approval to re-evaluate bec4f9c
bec4f9c to
eae2300
Compare
eae2300 to
719832d
Compare
719832d to
314ae86
Compare
Stack
Merge bottom-up — each PR is based on its parent below.
Android is the priority path: #4019 → #4011 → #4012 → #4016.
IntentState::Superseded(base:main)Already merged: #4018 (proto regen). Related follow-up, independent of this stack: #4020.
Exposes the unstable app-data change callback to the node bindings.
Shape
UnstableChangeCallbacksis a#[napi]class rather than an object, becauseThreadsafeFunctionis notToNapiValueand so cannot be an object field. Its constructor takes the callbacks as optional arguments, so adding a handler for another mutable field later is an additional optional parameter — additive for existing TS callers.The JS function returns a promise, which is awaited before message processing continues, so a semantic merge can finish before the next message is handled.
group_idis hex-encoded on this boundary, matching how the node bindings surface every other id.Error handling
A host callback that throws is logged and swallowed. The commit is already durable by the time the callback runs, so there is nothing to roll back; the only sane recovery is to let the next change re-trigger the merge. Propagating would abort message processing for a group over a host-side bug.
Registration
A trailing
changeCallbacksparameter oncreateClient,createClientWithBackend, and the shared inner constructor.undefinedregisters nothing.🤖 Generated with Claude Code
https://claude.ai/code/session_01AdY7WKkNbJmdzpmUWvW1my
Note
Expose app data change callbacks and compare-and-swap guard for group updates in Node bindings
UnstableChangeCallbacksregistry (core, FFI, and Node/mobile/Android bindings) that lets callers register an async callback to receiveAppDataChangenotifications after a group'sapp_datacommits, dispatched outside group locks.update_app_data: callers may supply anexpected_value; if the committed value no longer matches at publish time, the intent is markedSupersededand a non-retryableAppDataSupersedederror is returned.IntentState::Supersededto the DB schema and intent state machine, with a newset_group_intent_supersededDB method that only transitions fromToPublish.ClientBuilder→XmtpMlsLocalContext→XmtpSharedContexttrait and dispatched insync_with_conn(after mutex release) and in the streamingProcessMessageFactorypath.AppDataSupersededis a new non-retryable error surface visible to all callers ofupdate_app_data; existing callers must passNoneas the new second argument.📊 Macroscope summarized 314ae86. 21 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.