Repository navigation
fix(api): invalidate the heartbeat cache when events are inserted - #178
Conversation
|
|
CI-green and mergeable — waiting only on a maintainer click. This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted. |
🤖 AI code reviewThis PR invalidates the ServerAPI.last_event heartbeat cache in create_events, delete_event, and delete_bucket so that a subsequent heartbeat re-reads the stored last event instead of merging into a stale cached one. It adds two tests covering heartbeat-after-insert and heartbeat-after-delete scenarios. Needs a look — P2 onlyConfidence 4/5 1 finding ·
|
| commit | score | findings | engine | when |
|---|---|---|---|---|
039b9967d8fc |
3/5 | 2 | llm | 2026-10-02 06:03 UTC |
fbe982324cc2 |
5/5 | 0 | llm | 2026-10-02 11:02 UTC |
Reviewed 714aa270a4f0 · openrouter/deepseek/deepseek-v4-flash-0731 · llm engine · 158s · about this reviewer
Maintainer commands
@TimeToBuildBob review (own line) — fresh review · @TimeToBuildBob fix — a worker acts on the findings. Once per comment; 👀 = received.
|
Addressed the P1 from the review: |
fbe9823 to
25330e2
Compare
|
Rebased onto current Local verification: the 3 heartbeat-after-insert/delete cases pass; Black and Ruff pass. Fresh CI is running. |
create_events left ServerAPI.last_event untouched, so a heartbeat after an insert merged into the stale pre-insert event and replace_last() overwrote the newest inserted event. aw-server-rust already invalidates its cache on insert (aw-datastore worker, InsertEvents). Git-Session-Id: 3ed7
Deleting an event that was also the cached heartbeat last_event left self.last_event pointing at a deleted event. A subsequent heartbeat with matching data merged into the deleted event and replace_last() then operated on whatever event was now stored last (or an empty bucket). Pop the cache in delete_event and delete_bucket, same as create_events, and add a regression test. Git-Session-Id: c76bacd2-1c05-56ff-83b6-d9353e6533c5
…lack) Git-Session-Id: dafd
Git-Session-Id: 7fb7
25330e2 to
714aa27
Compare
|
Rebased again onto Local verification: 112 passed (14 client-integration tests deselected); pinned CI Ruff 0.15.22 and Black 23.3.0 pass; |
|
@greptileai review |
|
Greptile's 4/5 here is driven by one concern: CSV export columns colliding with data keys named I've made no change on this branch. CI is green on The collision is real but small. A data key named |
|
The CSV column collision is now fixed separately in both servers, using the same scheme: #184 and ActivityWatch/aw-server-rust#795. If a data key collides with an earlier header name, it gets a |
Bug
ServerAPI.create_eventsdoes not invalidateself.last_event[bucket_id]. A heartbeat that follows an insert therefore merges into the cached pre-insert event. When its data matches that event and it falls within pulsetime,replace_last()writes the merge over the newest stored event, which is one of the inserted ones. That event's data is lost.aw-server-rust already does this: its datastore worker resets
last_heartbeatin theInsertEventsarm.Why now
I found this while building ActivityWatch/aw-client#128, which bulk-inserts a drained queue backlog between heartbeats. On v0.13.2, queueing
a,b,c,alostc. That PR works around the bug client-side by only bulk-inserting when the run is longer than pulsetime. This PR fixes the bug itself, for any client that mixes inserts and heartbeats.This is related to, but separate from, #177 (replace by id). With only #177, the stale event is not overwritten but instead stretches over the inserted ones, so the two events overlap. With this PR the heartbeat re-reads the real last event.
Tests
test_heartbeat_after_insert_does_not_merge_into_stale_event(1 and 2 inserted events). Both cases fail on master because the inserted events are lost; both pass with the fix.pytest tests --deselect tests/test_client.py: 104 passed. The threebenchmark-fixture tests needpytest-benchmark, which my local env lacks; CI has it.