fix(node): record zenoh-delivered inputs in the write_events_to log - #3103
Draft
phil-opp wants to merge 2 commits into
Draft
fix(node): record zenoh-delivered inputs in the write_events_to log#3103phil-opp wants to merge 2 commits into
write_events_to log#3103phil-opp wants to merge 2 commits into
Conversation
EventStream::record_event only serialized daemon-path `NodeEvent::Input` events; `EventItem::ZenohInput` fell through the outer `_ => None` arm and was never pushed to the recording buffer. Both variants surface to the user as `Event::Input`, but the zenoh data plane bypasses the daemon, so neither the recorder nor the daemon captured those inputs — a dataflow whose node-to-node inputs take the direct zenoh path (the optimized common case) produced a `write_events_to` recording that silently omitted them while still reporting `recording_status: clean`. Add a `ZenohInput` arm that serializes the already-decoded array through a new `convert_arrow_input_to_json` entry point. The JSON encoding is refactored out of `convert_output_to_json` into shared `json_header` + `append_arrow_array_json` helpers so the daemon-path and zenoh-path recordings can never drift. Adds a unit test for the zenoh serialization. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1Fmp8pELuTiPGTStomkZj
Contributor
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
A zenoh-delivered input can carry a remote HLC timestamp earlier than this node's start_timestamp. json_header computed the offset with Timestamp::get_diff_duration, an unguarded NTP64 (u64) subtraction that underflows in that case — a debug panic (which unwinds past add_event's Err guard and kills the event loop) or a release wraparound to a garbage time_offset_secs. Clamp to a zero offset when the input predates start. The daemon path only records locally-timestamped inputs (always >= start), so it is unaffected. Adds a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1Fmp8pELuTiPGTStomkZj
Collaborator
Author
|
🤖 Automated review by Claude Code — fully automated review, not vetted by a human. No issues found. I verified the fix against the code:
Generated by Claude Code |
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.
Issue
EventStream::record_event(apis/rust/node/src/event_stream/mod.rs) serializes events into the optionalwrite_events_torecording. It only handled the daemon/TCP path input variant:EventItemhas two input-bearing variants —NodeEvent::Input(daemon path) andZenohInput(the direct zenoh data plane added in #2366). Both are converted to a user-visibleEvent::Inputbyconvert_event_item, i.e. they are the same class of event to the user. ButZenohInputfell through the outer_ => None, so it was never recorded.Because the zenoh data plane bypasses the daemon entirely, the daemon cannot record these inputs either. So for any dataflow whose node-to-node inputs take the direct zenoh path (the optimized common case), the
write_events_toJSON silently loses those inputs — while still reportingrecording_status: clean. Replay tools and integration-test oracles get an incomplete recording that looks complete. No error is raised, so the #1857 poisoning machinery doesn't catch it — the events are simply dropped.Fix
ZenohInputarm torecord_eventthat serializes the already-decodedArrayDataand tags it"type": "Input", mirroring theNodeEvent::Inputarm.convert_output_to_jsoninto sharedjson_header+append_arrow_array_jsonhelpers, and add aconvert_arrow_input_to_jsonentry point that takes an already-decodedArrayRef(the daemon path decodes aDataMessagefirst; the zenoh path is already decoded). Sharing the encoder keeps the two recording paths from drifting.Validation
zenoh_input_serializes_into_recording_json, asserting aZenohInput's array serializes into the sameid/data/data_typerecording shape with all elements present.cargo +1.97.1 fmt -p dora-node-api -- --check— clean.cargo +1.97.1 clippy -p dora-node-api -- -D warnings— clean.cargo +1.97.1 test -p dora-node-api --lib zenoh_input_serializes— passes.🤖 Generated with Claude Code
Generated by Claude Code