-
-
Notifications
You must be signed in to change notification settings - Fork 73
fix(datastore): use event ID instead of max(endtime) in replace_last_event #555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(datastore): use event ID instead of max(endtime) in replace_last_event #555
Conversation
…event Fixes a critical bug where heartbeat merges would target the wrong event due to a mismatch between get_events (ORDER BY starttime DESC) and replace_last_event (WHERE endtime = max(endtime)). When events have the same starttime but different durations (common during AFK status transitions), these queries target different events, causing: - Duplicate events - Failed heartbeat merges (events with 0 duration) - Cache/DB inconsistency Changes: - replace_last_event now takes event_id parameter and uses WHERE id = ? - Check rows_affected and error if 0 rows updated (cache inconsistency) - heartbeat passes last_event.id to ensure correct event is updated Fixes ActivityWatch#554 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important
Looks good to me! 👍
Reviewed everything up to e9ec01d in 42 seconds. Click for details.
- Reviewed
51lines of code in1files - Skipped
0files when reviewing. - Skipped posting
4draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. aw-datastore/src/datastore.rs:551
- Draft comment:
Changing the function signature to include an event_id parameter ensures that the update is targeted deterministically, which directly addresses the mismatch described in #554. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
2. aw-datastore/src/datastore.rs:560
- Draft comment:
The SQL UPDATE now uses ‘WHERE bucketrow = ?1 AND id = ?5’, which correctly targets the specific event by its ID. This avoids ambiguity when multiple events share the same starttime. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
3. aw-datastore/src/datastore.rs:592
- Draft comment:
Good job checking for zero rows affected. Returning an error when no rows are updated helps catch potential cache/DB inconsistencies immediately. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
4. aw-datastore/src/datastore.rs:639
- Draft comment:
Extracting the event_id from last_event in the heartbeat function ensures that the correct event is updated. The error handling for a missing ID is appropriate. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
Workflow ID: wflow_MYWpdUaHZvG1U4Vx
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
Greptile OverviewGreptile SummaryFixed critical heartbeat merge bug by aligning event selection logic between Problem: Changes:
Impact: This fix prevents massive event duplication. In real-world data (8 months), this bug caused 284,995 AFK events when there should have been ~10,816 (96% duplicates), with 92% of events having 0 duration because heartbeats never merged. Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant Datastore
participant Cache
participant DB
participant Transform
Client->>Datastore: heartbeat(bucket_id, heartbeat_event, pulsetime)
Datastore->>Cache: check last_heartbeat cache
alt Cache hit
Cache-->>Datastore: return cached last_event
else Cache miss
Datastore->>DB: get_events(LIMIT 1, ORDER BY starttime DESC)
DB-->>Datastore: return last_event with ID
end
Datastore->>Transform: heartbeat(last_event, heartbeat_event, pulsetime)
alt Data matches and within pulsetime
Transform-->>Datastore: return merged_heartbeat
Note over Datastore: Extract event_id from last_event
Datastore->>DB: UPDATE events WHERE id = event_id
DB-->>Datastore: rows_affected
alt rows_affected == 0
Datastore-->>Client: Error: cache/DB inconsistency
else rows_affected > 0
Datastore->>Cache: update last_heartbeat cache
Datastore-->>Client: return merged_heartbeat
end
else Data differs or outside pulsetime
Transform-->>Datastore: return None
Datastore->>DB: insert_events(new heartbeat)
DB-->>Datastore: new event with ID
Datastore->>Cache: update last_heartbeat cache
Datastore-->>Client: return new event
end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No files reviewed, no comments
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #555 +/- ##
==========================================
- Coverage 70.81% 67.82% -3.00%
==========================================
Files 51 54 +3
Lines 2916 3139 +223
==========================================
+ Hits 2065 2129 +64
- Misses 851 1010 +159 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@Sinity Thanks a lot for linking the transcript, I enjoyed reading it |
|
Lets hope this finally gets rid of all the 0-duration duplicate events. Thanks a lot! |
Summary
Fixes #554 - a critical bug where heartbeat merges target the wrong event due to SQL query mismatch.
Problem
get_eventsusesORDER BY starttime DESC LIMIT 1whilereplace_last_eventusesWHERE endtime = (SELECT max(endtime)). When events have the same starttime but different durations, these select different events.This causes:
Solution
replace_last_eventnow takesevent_idparameter and usesWHERE id = ?rows_affectedand error if 0 rows updated (detects cache inconsistency)heartbeatpasseslast_event.idto ensure the correct event is updatedTesting
All existing tests pass including
test_event_heartbeat.Impact
In real-world data (8 months):
🤖 Generated with Claude Code
Important
Fixes critical bug in
replace_last_eventby usingevent_idfor updates, ensuring consistency withget_eventsand preventing duplicate events.replace_last_eventnow usesevent_idinstead ofmax(endtime)to update events, ensuring consistency withget_eventsordering.replace_last_eventto detect cache inconsistencies if 0 rows are updated.heartbeatfunction updated to passlast_event.idtoreplace_last_event.test_event_heartbeat.This description was created by
for e9ec01d. You can customize this summary. It will automatically update as commits are pushed.