Skip to content

Move unique stats duration calculation to Heartbeatable - #1660

Open
skyfallwastaken wants to merge 1 commit into
mainfrom
refactor/stats-authoritative-duration
Open

skyfallwastaken wants to merge 1 commit into
mainfrom
refactor/stats-authoritative-duration

Conversation

@skyfallwastaken

Copy link
Copy Markdown
Member

Summary of the problem

StatsController#user_stats calculated unique_total_seconds with controller-local timestamp ordering and timeout handling even though Heartbeatable owns heartbeat duration semantics.

Describe your changes

Moved the distinct over-timeout gap calculation into a narrowly named Heartbeatable relation method and made the endpoint delegate to it. The established coding-only, valid timestamp and project filter behaviour is preserved, including exact timeout and date boundary handling. Added endpoint regression coverage against the authoritative relation result, including test_param mode.

Screenshots / Media

Not applicable. There are no visual changes.

Copilot AI lite review requested due to automatic review settings September 1, 2026 02:37
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR moves project-filtered unique heartbeat duration calculation from the stats controller into Heartbeatable while preserving the existing timeout, ordering, timestamp-validity, and filtering semantics.

  • Adds a relation-aware SQL aggregation that excludes non-positive gaps and gaps over the heartbeat timeout.
  • Updates the stats endpoint to delegate to the new relation method.
  • Adds endpoint regression coverage for filtering, timeout/date boundaries, and invalid timestamps in test mode.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness, security, or quality issues identified.

The filtered relation remains intact through Active Record relation scoping, and the new PostgreSQL aggregation preserves the former positive-gap, inclusive two-minute timeout, ordering, and timestamp-validity behavior with targeted endpoint coverage.

Important Files Changed

Filename Overview
app/controllers/api/v1/stats_controller.rb Replaces the controller-local duration helper with delegation to the filtered heartbeat relation without changing endpoint reachability or filters.
app/models/concerns/heartbeatable.rb Adds PostgreSQL window-function aggregation whose ordering, validity filtering, timeout boundary, and integer result match the removed calculation.
test/controllers/api/v1/stats_controller_test.rb Adds regression tests covering project/category/date filtering, exact timeout behavior, out-of-range records, and invalid timestamps.

Reviews (1): Last reviewed commit: "Move unique stats duration to Heartbeata..." | Re-trigger Greptile

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR moves the calculation of unique_total_seconds out of StatsController#user_stats and into the Heartbeatable concern, so heartbeat duration semantics (timeout gap handling and timestamp validity filtering) live with the model layer rather than being duplicated in the controller.

Changes:

  • Replaced the controller-local unique_heartbeat_seconds implementation with a delegated relation-level calculation.
  • Added Heartbeatable.duration_seconds_excluding_gaps_over_timeout to compute coding duration while excluding gaps larger than the heartbeat timeout.
  • Added regression tests asserting the endpoint’s unique_total_seconds matches the authoritative relation result across timeout, project filter and timestamp validity scenarios (including test_param mode).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
app/controllers/api/v1/stats_controller.rb Delegates unique_total_seconds computation to the Heartbeatable relation method and removes the controller-local implementation.
app/models/concerns/heartbeatable.rb Introduces a SQL/window-function based duration calculator that excludes gaps over the timeout threshold.
test/controllers/api/v1/stats_controller_test.rb Adds controller-level regression coverage ensuring API results match the new authoritative model-layer calculation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +253 to +256
def duration_seconds_excluding_gaps_over_timeout(scope = all)
scope = scope.with_valid_timestamps
heartbeat_gaps = scope.select("LAG(time) OVER (ORDER BY time, #{quoted_table_name}.id) as duration_start, time as duration_end").where.not(time: nil)
timeout = heartbeat_timeout_duration.to_i

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants