fix(query): configurable flood pulsetime to fix missing time with high poll intervals#875
Conversation
Previously the import UI showed nothing on success (the null response was silent) and displayed only a generic fallback message on failure regardless of what the server reported. - Add a dismissible success alert shown after a successful import - Extract the server error message from the response body and display it; fall back to the generic message if no structured error is present - Add import_success flag to data() to drive the new success alert Fixes ActivityWatch/activitywatch#394 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR makes the
Confidence Score: 4/5Safe to merge once backward compatibility of the extra The core feature is straightforward and the default (5 s) preserves existing behaviour exactly. The main uncertainty is whether passing a second positional argument to src/queries.ts — the Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as User (Developer Settings)
participant DeveloperSettings as DeveloperSettings.vue
participant SettingsStore as stores/settings.ts
participant ActivityStore as stores/activity.ts
participant Queries as queries.ts
participant Server as aw-server
User->>DeveloperSettings: Set floodPulsetime (e.g. 31)
DeveloperSettings->>SettingsStore: "update({ floodPulsetime: 31 })"
SettingsStore-->>SettingsStore: persist to server/localStorage
Note over ActivityStore: On activity view load
ActivityStore->>SettingsStore: useSettingsStore().floodPulsetime
SettingsStore-->>ActivityStore: 31
ActivityStore->>Queries: "fullDesktopQuery({ ..., floodPulsetime: 31 })"
Queries->>Queries: "canonicalEvents() pulsetime = 31"
Queries->>Queries: "browserEvents() pulsetime = 31"
Queries-->>ActivityStore: query string with flood(..., 31)
ActivityStore->>Server: POST /query with flood(bucket, 31)
Server-->>ActivityStore: events with gaps filled up to 31s
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as User (Developer Settings)
participant DeveloperSettings as DeveloperSettings.vue
participant SettingsStore as stores/settings.ts
participant ActivityStore as stores/activity.ts
participant Queries as queries.ts
participant Server as aw-server
User->>DeveloperSettings: Set floodPulsetime (e.g. 31)
DeveloperSettings->>SettingsStore: "update({ floodPulsetime: 31 })"
SettingsStore-->>SettingsStore: persist to server/localStorage
Note over ActivityStore: On activity view load
ActivityStore->>SettingsStore: useSettingsStore().floodPulsetime
SettingsStore-->>ActivityStore: 31
ActivityStore->>Queries: "fullDesktopQuery({ ..., floodPulsetime: 31 })"
Queries->>Queries: "canonicalEvents() pulsetime = 31"
Queries->>Queries: "browserEvents() pulsetime = 31"
Queries-->>ActivityStore: query string with flood(..., 31)
ActivityStore->>Server: POST /query with flood(bucket, 31)
Server-->>ActivityStore: events with gaps filled up to 31s
Reviews (1): Last reviewed commit: "fix(query): make flood pulsetime configu..." | Re-trigger Greptile |
| return [ | ||
| // Fetch window/app events | ||
| `events = flood(${queryBucket(bid_window)});`, | ||
| `events = flood(${queryBucket(bid_window)}, ${pulsetime});`, |
There was a problem hiding this comment.
Extra argument may break
flood() on older aw-server versions
The PR description notes this change pairs with aw-core#139, which adds pulsetime as a named parameter to flood(). Users running an aw-server version that predates that change will suddenly receive a query with an unexpected second positional argument. Depending on how the query language dispatcher handles extra args, this could result in a TypeError or similar runtime error that causes all activity queries to fail — with no fallback.
Before landing, it is worth confirming that the aw-core query interpreter silently ignores extra positional arguments when flood() is called with the old signature, and documenting the minimum required aw-server version if not.
| showYearly: false, | ||
| useMultidevice: false, | ||
| requestTimeout: 30, | ||
| floodPulsetime: 5, |
There was a problem hiding this comment.
No store-level bounds validation for
floodPulsetime
The HTML input enforces min="1", but the store's update() action accepts any value passed to it directly (e.g. from tests, direct API calls, or a malformed server response). A value of 0 or a negative number would silently produce flood(query_bucket("..."), 0) in the generated query string, which likely has undefined behaviour in the query language. Adding a clamp or guard (e.g. Math.max(1, value)) inside the setter or the update action would be more defensive.
…h high poll intervals Users who raise the watcher polling interval above 5s lose trackable time because the default 5s pulsetime in flood() no longer fills the inter-poll gaps. A user working 8h could see only 7.5h in the dashboard. Changes: - queries.ts: add optional floodPulsetime to BaseQueryParams (default 5); pass it as the explicit second argument to all flood() calls in canonicalEvents() and browserEvents() - settings.ts: add floodPulsetime: number (default 5, persisted like other settings) - stores/activity.ts: thread useSettingsStore().floodPulsetime into both fullDesktopQuery and multideviceQuery param objects - DeveloperSettings.vue: add a number input for floodPulsetime with guidance text explaining the poll_interval + 1 rule The default of 5 is fully backward-compatible. Users who increased their polling interval can now set this to polling_interval + 1 in Developer Settings and immediately recover the missing time. Pairs with aw-core fix: ActivityWatch/aw-core#139 Fixes ActivityWatch/activitywatch#1177 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
e2eb207 to
637abe9
Compare
Summary
Fixes ActivityWatch/activitywatch#1177
Users who raise the watcher polling interval above 5s lose trackable time because the default 5s
pulsetimeinflood()no longer fills the inter-poll gaps. A user working 8h could see only 7.5h in the dashboard.Changes:
queries.ts: Add optionalfloodPulsetimefield toBaseQueryParams(default5); pass it as an explicit second argument to everyflood()call insidecanonicalEvents()andbrowserEvents()stores/settings.ts: AddfloodPulsetime: number(default5) — persisted like all other settingsstores/activity.ts: IncludefloodPulsetime: useSettingsStore().floodPulsetimein bothfullDesktopQueryandmultideviceQueryparam objectsviews/settings/DeveloperSettings.vue: Add a number input for "Flood pulsetime (seconds)" with descriptive help text explaining thepolling_interval + 1ruleTest plan
floodPulsetimedefaults to5, all existing queries behave identically31in Developer Settings → gaps are filled, reported time matches clock time