Skip to content

RPC: Fix getObject() desync bugs#6835

Merged
knutwannheden merged 3 commits intomainfrom
deft-panda
Feb 27, 2026
Merged

RPC: Fix getObject() desync bugs#6835
knutwannheden merged 3 commits intomainfrom
deft-panda

Conversation

@knutwannheden
Copy link
Copy Markdown
Contributor

@knutwannheden knutwannheden commented Feb 26, 2026

Summary

Three fixes for RPC state desynchronization issues during composite recipe execution.

1. Fix getObject() diff baseline

getObject() in Java and TypeScript used localObjects as the diff baseline when receiving trees from the remote peer. The remote computes diffs against remoteObjects (the last synced state). When the local side modifies a tree via a local recipe before calling getObject(), the baselines diverge, producing corrupt data.

Fixed both Java and TypeScript to use remoteObjects as the baseline. Added a back-to-back RPC test that reproduces the bug by verifying that Markers (an object field sent as NO_CHANGE) comes from the synced baseline, not from locally modified state.

2. Reset remote object tracking on getObject() failure

When getObject() fails mid-deserialization, the sender has already updated its tracking of what the receiver has, but the receiver never applied the change. Subsequent operations compute diffs against the wrong baseline.

Fixed by removing remoteObjects[id] when receive() throws in all three implementations (Java, TypeScript, Python).

3. Fix Python get_object_from_java missing END_OF_OBJECT on batch boundary

Python's get_object_from_java strips END_OF_OBJECT from batches and tracks it with a flag. When serialized data items are an exact multiple of the handler's batchSize, END_OF_OBJECT ends up alone in a separate batch that receive() never pulls.

Fixed by draining the pending batch after receive() completes — analogous to Java/JS's explicit q.take().

Test plan

  • rewrite-core RPC tests pass (including new getObjectUsesRemoteObjectsAsBaseline test)
  • rewrite-javascript RPC tests pass

@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Feb 26, 2026
@knutwannheden knutwannheden force-pushed the deft-panda branch 3 times, most recently from a46d435 to 140c5b9 Compare February 27, 2026 06:55
@knutwannheden knutwannheden changed the title RPC: Fix getObject() using wrong diff baseline RPC: Fix getObject() desync bugs Feb 27, 2026
getObject() used localObjects as the diff baseline when receiving from
the remote peer. But the remote computes diffs against the last synced
state (remoteObjects), not the local state. When the local side modifies
a tree (e.g., via a local recipe) before calling getObject(), the two
baselines diverge, producing a hybrid tree that corrupts remoteObjects
and causes subsequent transfers to fail with IndexError/desync.

Fix: use remoteObjects (the last synced state) as the baseline, matching
what the remote peer uses. Python's get_object_from_java() already did
this correctly; Java and TypeScript had the same bug.
…tate desync

When getObject() fails mid-deserialization (e.g., ClassCastException), the
sender has already updated its tracking of what the receiver has, but the
receiver never applied the change. This causes all subsequent RPC interactions
for that object to compute diffs against the wrong baseline, leading to
"Expected positions array" and similar desync errors.

Fix by removing remoteObjects[id] when receive() throws, so the next
interaction sends a full ADD (no delta), re-synchronizing both sides.

Also fix Python's handle_visit() to always fetch the tree from Java via
get_object_from_java(), matching the JS implementation. The previous code
used a stale local_objects cache, which meant Python could operate on an
outdated tree version after Java-side modifications or error recovery.
…oundary

When serialized data items are an exact multiple of the handler's
batchSize, END_OF_OBJECT ends up alone in a separate batch that
receiver.receive() never pulls. Drain the pending batch after
receive() completes — analogous to Java/JS's explicit q.take().

Add integration test with small batchSize to exercise the fix.
@knutwannheden knutwannheden marked this pull request as ready for review February 27, 2026 07:20
@knutwannheden knutwannheden changed the title RPC: Fix getObject() desync bugs RPC: Fix getObject() desync bugs Feb 27, 2026
@knutwannheden knutwannheden merged commit f93dd01 into main Feb 27, 2026
1 check passed
@knutwannheden knutwannheden deleted the deft-panda branch February 27, 2026 07:54
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant