async recorder callbacks#2577
Conversation
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #2577 +/- ##
==========================================
+ Coverage 69.61% 70.87% +1.26%
==========================================
Files 878 866 -12
Lines 79326 77253 -2073
Branches 7126 6875 -251
==========================================
- Hits 55220 54755 -465
+ Misses 22301 20695 -1606
+ Partials 1805 1803 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 14 files with indirect coverage changes 🚀 New features to boost your workflow:
|
27a5a72 to
6276f5b
Compare
Convert the memory2 Recorder from thread/disposable rx subscriptions to manual async callbacks via process_observable, and let pose_setter_for methods be async (awaited in _resolve_pose). Update the fastlio and go2 recorders accordingly.
6276f5b to
dba1e5a
Compare
Raise TypeError at decoration time if a non-async function is decorated, and always await the setter in _resolve_pose.
…imos into jeff/fix/pose_setter_for
Greptile SummaryThis PR migrates
Confidence Score: 5/5Safe to merge — all known users of The changes are mechanical and well-scoped: a new optional parameter is threaded through the dispatcher, the decorator adds a static check, and the three concrete recorder classes are updated consistently. No existing dispatch logic is altered and the only callsites for No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Src as Input Topic (thread)
participant Slot as LATEST Slot (event loop)
participant Disp as Dispatcher Task
participant CB as async on_msg
participant Drop as _on_frame_dropped
Src->>Slot: call_soon_threadsafe(_set)
alt slot already has value
Slot->>Drop: on_drop() — frame lost
end
Slot->>Slot: overwrite value, set event
Disp->>Slot: await event, consume value
Disp->>CB: await on_msg(msg)
CB->>CB: _resolve_ts / await _resolve_pose
CB->>CB: stream.append(msg, ts, pose)
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Src as Input Topic (thread)
participant Slot as LATEST Slot (event loop)
participant Disp as Dispatcher Task
participant CB as async on_msg
participant Drop as _on_frame_dropped
Src->>Slot: call_soon_threadsafe(_set)
alt slot already has value
Slot->>Drop: on_drop() — frame lost
end
Slot->>Slot: overwrite value, set event
Disp->>Slot: await event, consume value
Disp->>CB: await on_msg(msg)
CB->>CB: _resolve_ts / await _resolve_pose
CB->>CB: stream.append(msg, ts, pose)
Reviews (2): Last reviewed commit: "recorder: count + warn on frames dropped..." | Re-trigger Greptile |
| stream.append(msg, ts=ts, pose=pose) | ||
|
|
||
| self.register_disposable(Disposable(input_topic.subscribe(on_msg))) | ||
| self.process_observable(input_topic.pure_observable(), on_msg) |
There was a problem hiding this comment.
Silent frame drops under sustained high-frequency input
process_observable uses a single-slot LATEST mailbox: if on_msg is still awaiting _resolve_pose / stream.append when the next message arrives, the queued-but-unprocessed item is silently overwritten. The old Disposable(input_topic.subscribe(on_msg)) approach would block the publisher instead of dropping.
For typical sensor rates and a fast SQLite write this should be fine in practice, but there's no dropped-frame counter or warning anywhere — if the DB slows down or a pose setter blocks, missing frames would be invisible. Consider logging a warning (or incrementing a counter) inside the LATEST-coalescing slot in _make_async_dispatch, or in on_msg itself if a pre-existing slot is detected, so operators know when data is being lost.
There was a problem hiding this comment.
good idea, I'll add a warning for dropped stuff
process_observable gains an optional on_drop callback fired once per message dropped by the dispatcher's single-slot LATEST mailbox. The Recorder uses it to count dropped frames per stream and log a throttled warning, so a slow sink no longer loses data silently.
Async
pose_setter_forfor memory2. Updates the fastlio and go2 recorders to match.