Problem
The rowid-cursor sync introduced in #789 doesn't re-fetch events whose endtime was extended by a heartbeat after the event's rowid was synced.
Scenario:
- Event A (rowid 100, T1–T2) is synced → cursor saved at 100
- A heartbeat extends event A's
endtime to T2+30 (rowid still 100)
- Next sync:
get_events_since_rowid(100) returns only rowid > 100 → misses the T2→T2+30 extension
reconcile_updated_events handles the lookback window up to resume_sync_at but not extensions beyond that boundary
Impact
Bounded: only the trailing open event at sync time loses the heartbeat extension in the destination. The impact resolves on the next natural event transition (when a new event starts and the old one closes).
Tradeoff
This is a known tradeoff vs. the old timestamp-scan path:
Proposed fix
After the rowid fast-path, re-sync the highest-rowid event from source (the "trailing event") to capture any heartbeat extension since the previous cursor save. This is a small fixed-cost read per bucket per sync pass.
Related
Problem
The rowid-cursor sync introduced in #789 doesn't re-fetch events whose
endtimewas extended by a heartbeat after the event's rowid was synced.Scenario:
endtimeto T2+30 (rowid still 100)get_events_since_rowid(100)returns only rowid > 100 → misses the T2→T2+30 extensionreconcile_updated_eventshandles the lookback window up toresume_sync_atbut not extensions beyond that boundaryImpact
Bounded: only the trailing open event at sync time loses the heartbeat extension in the destination. The impact resolves on the next natural event transition (when a new event starts and the old one closes).
Tradeoff
This is a known tradeoff vs. the old timestamp-scan path:
endtime-only updatesProposed fix
After the rowid fast-path, re-sync the highest-rowid event from source (the "trailing event") to capture any heartbeat extension since the previous cursor save. This is a small fixed-cost read per bucket per sync pass.
Related