fix(android): wait for gateway connect before node events#79565
fix(android): wait for gateway connect before node events#79565TurboTheTurtle wants to merge 3 commits into
Conversation
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: yes. from source inspection: current main publishes currentConnection before the connect RPC completes, and notification forwarding can call sendNodeEvent during that window. I did not live-run a Pixel/Gateway reconnect scenario, so this is source-reproducible rather than live reproduced. Real behavior proof Next step before merge Security Review detailsBest possible solution: Merge this narrow Android runtime fix after exact-head Android validation is green and the contributor adds redacted real reconnect proof showing notification node events wait for connect and replay after reconnect. Do we have a high-confidence way to reproduce the issue? Yes from source inspection: current main publishes currentConnection before the connect RPC completes, and notification forwarding can call sendNodeEvent during that window. I did not live-run a Pixel/Gateway reconnect scenario, so this is source-reproducible rather than live reproduced. Is this the best way to solve the issue? Yes for the code direction: returning ready metadata, publishing the connection, then invoking onConnected is the narrow maintainable fix for the handshake race. The PR is not merge-ready until real Android/Gateway reconnect proof is attached. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against db2cc57cf11b. |
|
Updated the Android branch for the review finding: the connect callback now fires only after connectOnce has published the ready currentConnection, so queued notification events flush with a visible send-ready connection. I also updated the PR body with structured proof/validation. Local Android execution is still blocked by the missing Java runtime on this machine, so I’m relying on CI android-test-play for the Robolectric verification.\n\n@clawsweeper re-review |
|
Added the required changelog entry in Remaining blocker is still the reviewer-requested real Android/Gateway reconnect proof. This machine does not have the Android device/Gateway setup needed to generate redacted reconnect logs or a recording, so I am not claiming that proof yet. The PR body still has the CI/Robolectric/source validation, and a real device/Gateway trace should be added before merge. @clawsweeper re-review |
|
Closing this for now to keep the active PR queue under the project limit. The code direction is useful, but this still needs real Android/Gateway reconnect proof from an actual device or equivalent trace before it is worth reopening. |
Summary
Fixes #79552.
Android now publishes
GatewaySession.currentConnectiononly after the gatewayconnectRPC has completed, so reconnect-window callers cannot sendnode.eventas the first websocket request before the handshake. Notification listener events that arrive while reconnect is still in flight are retained in a bounded queue and flushed once the node session reconnects.Follow-up after review:
Connection.connect()now returns the parsed ready metadata instead of firingonConnectedinternally.connectOnce()assignscurrentConnection = connbefore invokingonConnected, soNodeRuntime.flushPendingForwardedNodeEvents()runs only after the ready connection is visible tosendNodeEvent.Real behavior proof
Behavior or issue addressed:
notifications.changedmust not be sent asnode.eventbefore the node gateway connection finishes theconnectRPC, and queued notification events must flush only after the ready connection is visible.Real environment tested: local OpenClaw checkout at
f5fb8104d11aon macOS. Local Android test execution is blocked on this machine because no Java runtime is installed, so the Android unit test is expected to be verified by CI after this push.Exact steps or command run after this patch: inspected and patched the real Android runtime path so
GatewaySession.Connection.connect()completes handshake parsing,GatewaySession.connectOnce()publishescurrentConnection, and only then invokesonConnected, which is the callback that starts notification queue flushing inNodeRuntime.Evidence after fix:
Observed result after fix: the queue flush callback now happens after
currentConnectionis populated, so a retainednotifications.changedevent can be sent through the newly ready connection instead of being drained whilesendNodeEventstill sees no connection.What was not tested: I did not run a live Android device or local Robolectric shard on this Mac because Java is unavailable locally. CI should run
android-test-playfor the pushed head.Before evidence: the previous PR head failed
android-test-playonGatewaySessionInvokeTest > sendNodeEventDetailed_doesNotSendBeforeConnectHandshakeCompletes, matching the review finding that the queue could flush whilecurrentConnectionwas still null.Validation
git diff --check./gradlew :app:testPlayDebugUnitTest --tests ai.openclaw.app.gateway.GatewaySessionInvokeTest.sendNodeEventDetailed_doesNotSendBeforeConnectHandshakeCompletesfromapps/android; local machine has no Java runtime installed:Unable to locate a Java Runtime.android-test-playshould verify the Android test after the pushed follow-up commit.Notes
The notification retry buffer is bounded to 64 events and drops the oldest entries under sustained reconnect/offline pressure to avoid unbounded memory growth.