perf: dirty-flag polling for channel unread checks#653
perf: dirty-flag polling for channel unread checks#653laynepenney merged 3 commits intosprint-17from
Conversation
|
Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement. To sign, please comment on this PR with the following exact text:
You can also re-trigger the CLA check by commenting I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
|
QA review — LGTM. Design is correct. Dirty flag separate from the read cursor is the right approach — O(1) check without changing existing unread semantics. Key invariants all hold: flag cleared only by Tests are thorough. 10 tests cover the full lifecycle plus edge cases: count-only doesn't clear (critical invariant), multiple posts single clear, pin sets dirty, directive sets dirty, non-member gets empty dict. Full suite at 1972 passed confirms no regressions. Minor note (non-blocking): Boundary declaration present and correct. Needs one more review. |
|
this needs to merge into sprint-17 branch, not main |
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Agents polling for unread messages previously scanned every channel's JSONL file and compared timestamps. This is O(messages) per poll for what is usually a "nothing changed" answer. Add an unread_flags table in the channels SQLite DB: - On any write (_append_message, channel_pin), set dirty=1 for all other channel members - channel_has_unread() checks the flag in a single SQLite read (~0.1ms) - Flag is only cleared by channel_read() (full read), NOT by channel_unread() (count-only) - Initialized clean on channel_join 10 tests covering the full write-flag-read-clear lifecycle. 1972 passed, 0 failed. Closes #638 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
e967e78 to
f25c0e8
Compare
Summary
unread_flagstable to channels SQLite DB for O(1) unread checkschannel_has_unread()returns in <1ms when nothing changed (single SQLite read vs JSONL scan)channel_read()(full read), NOT bychannel_unread()(count-only)channel_unread()behavior unchangedChanges
channel.py: Addedunread_flagstable schema,_set_dirty_flags()helper,channel_has_unread()function, dirty-flag set in_append_messageandchannel_pin, dirty-flag clear inchannel_readtest_channel.py: 10 new tests covering write-flag-read-clear lifecyclePremium boundary: this is OSS recall infrastructure. The dirty-flag optimization benefits all agents polling channels, reducing per-poll cost from O(channels x JSONL_size) to O(1).
Test plan
Closes #638
🤖 Generated with Claude Code