Repository navigation
fix(notify): ingest new usage events before checking alert thresholds - #338
Conversation
|
865cd5c to
b2f21b2
Compare
NotifyWorker queried category time without ingesting first, so alerts were judged against data last ingested by the hourly (inexact) alarm, an app open or a widget refresh.
Rebased onto ActivityWatch#329: ingestion now runs after the disabled/malformed early return, so a disabled aw-notify never touches activity data, and goes through NotifyBackend so the execution tests cover the ordering and the ingest-failure fallback.
b2f21b2 to
a4d0b82
Compare
|
Rebased onto master (after #329) and adjusted for the overlap: ingestion now runs after the disabled/malformed early return from #329, so a disabled @greptileai review |
🤖 AI code reviewAdds an ingestLatestUsage() method to the NotifyBackend interface and its RustNotifyBackend implementation, which calls SessionEventWatcher.processEventsSinceLastUpdate() when usage access is allowed. NotifyWorker.doWork() now calls backend.ingestLatestUsage() before querying thresholds, wrapping it in a try/catch that logs and continues on failure. The test FakeBackend gains a failIngest flag and the expected call sequence in tests is updated to include 'ingest'. Needs a look — P2 onlyConfidence 4/5 1 finding ·
|
TimeToBuildBob
left a comment
There was a problem hiding this comment.
Reviewed. The fix is correct and well-structured.
The placement of ingestLatestUsage() after the alerts.isEmpty() guard is right — no ingestion when disabled or nothing configured. The try/catch gracefully degrades to checking stored data on failure. The processEventsSinceLastUpdate() lock means overlapping runs from the hourly alarm or app open are harmless.
Test coverage through the NotifyBackend seam is clean: the call-ordering test now catches any regression, and ingestFailureStillChecksStoredData covers the fallback path. CI green across all three variants.
One advisory the AI reviewer noted: RustNotifyBackend creates a fresh SessionEventWatcher on each call. Fine for a 15-minute periodic worker, but worth caching if we ever raise the frequency.
|
Review dispositions for a4d0b82: the Bob P2 on the |
Part of #333.
NotifyWorkerruns every 15 minutes and queries today's category time, but it never ingested new usage events first. Those only reach the datastore on the hourly (inexact) logging alarm, on app open, or on widget refresh. Alerts were therefore judged against data up to an hour old, and a threshold could be crossed well before the notification fired.Change
NotifyWorkerrunsSessionEventWatcher.processEventsSinceLastUpdate()when usage access is granted.EventParsingWorkeruses the same synchronous call.processEventsSinceLastUpdateguards against concurrent runs with its own lock, so an overlapping run from the alarm or the app just skips.Pairs with #337, which makes the in-progress session count. Together, an alert can fire while the user is still in the app.
Testing
./gradlew :mobile:testStandardDebugUnitTestpasses.Workerthat needs a live datastore andUsageStatsManager, so it has no new unit test.