Skip to content

Fix weekly reports and analytics worker microbatches - #1190

Merged
Asherlc merged 9 commits into
mainfrom
Asherlc/fix-weekly-health-summary
May 27, 2026
Merged

Asherlc merged 9 commits into
mainfrom
Asherlc/fix-weekly-health-summary

Conversation

@Asherlc

@Asherlc Asherlc commented May 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Fix weekly report week bucketing and display logic for activity/recovery edge cases.
  • Bound the analytics activity graph to each dbt microbatch window and keep the BullMQ worker independent from analytics dbt builds.
  • Pin the Ultrahuman integration test clock to the fixture date it asserts.

Verification

  • CLICKHOUSE_URL=http://default:health@127.0.0.1:$(docker compose port clickhouse 8123 | sed 's/.*://') pnpm lint
  • pnpm tsc --noEmit; cd packages/server && pnpm tsc --noEmit; cd packages/web && pnpm tsc --noEmit
  • Focused Vitest suites for weekly report, analytics microbatch, Ultrahuman sync, and predictions passed; full pnpm test:changed hit a late-suite local ClickHouse memory limit in analytics.v_sleep, while the failed file passed in isolation.

Summary by cubic

Fixes weekly report Sunday bucketing and training load math. Bounds and aligns the activity graph per microbatch to stop ClickHouse OOMs and keep the BullMQ worker independent from analytics builds.

  • Bug Fixes
    • Weekly report: Sunday-start weeks, always returns the latest week, counts all ended activities, computes training load only when avg HR exists, ignores join-default zeros, and shows “No training” when a week has no activities.
    • Adds bounded_activity_graph() and switches sensor/location read models to it; bounds to the microbatch window via __dbt_internal_microbatch_event_time_start/end, and selects canonical activities using provider/device priority; adds provider_priority and device_priority sources.
    • Aligns graph windows: uses a 12-hour default for null-ended activities in overlap checks and merges group min start/max end for sensor membership.
    • entrypoint.sh no longer runs dbt build for worker; the BullMQ worker starts independently.
    • Tests assert bounded macro usage and window alignment, worker decoupling, and pin the Ultrahuman test clock.

Written for commit d67e3b4. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Enhanced weekly report status indicators to distinguish "no training" from "sleep not tracked" scenarios.
  • Bug Fixes

    • Fixed weekly report week boundaries to use Sunday-start weeks.
    • Corrected training load and vital stats (resting HR/HRV) aggregation in weekly summaries.
    • Resolved background worker stability issues from memory constraints.

Review Change Stack

Copilot AI review requested due to automatic review settings May 27, 2026 01:40
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@surmado-code-review

surmado-code-review Bot commented May 27, 2026 •

Copy link
Copy Markdown

Automated Checks (advisory, non-blocking)

✅ All checks passed.


Surmado Code Review — Free tier limit reached

You've used all 10 free reviews this month. Deterministic checks (secrets, model strings) still ran above.

Upgrade to the Paid plan for 100 reviews/month + $15 per additional 100: https://app.surmado.com/checkout?plan=pr_review_starter

Or wait until your next monthly window for 10 more free reviews.


Surmado Code Review (v1.2-mt)

@sourcery-ai sourcery-ai Bot 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.

Sorry @Asherlc, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented May 27, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR fixes a production OOM incident by introducing a microbatch-bounded bounded_activity_graph() macro in dbt ClickHouse, applying it to analytics read models, decoupling worker startup from dbt builds, migrating weekly report aggregation from ISO Monday to Sunday weeks with improved null handling, and updating the weekly report card UI to distinguish "no training" from "sleep not tracked" states.

Changes

Bounded Activity Graph and Analytics Model Refactoring

Layer / File(s) Summary
Bounded activity graph macro with microbatch windowing
analytics/macros/bounded_activity_graph.sql, analytics/models/sources.yml, analytics/models/read_models/read_model_microbatch.sql.test.ts
Macro computes time-windowed activity graphs by filtering to microbatch bounds, deriving device/provider priorities, building overlap-based edges, computing connected components, selecting canonical activities, and exposing current_activity and activity_members CTEs. Sources configuration adds device_priority and provider_priority tables. Tests assert macro references microbatch time bounds and produces bounded output.
Analytics models switch to bounded_activity_graph macro
analytics/models/read_models/activity_location_sample.sql, analytics/models/read_models/activity_sensor_sample.sql, analytics/models/read_models/read_model_microbatch.sql.test.ts
Models now invoke WITH RECURSIVE {{ bounded_activity_graph() }} instead of local CTEs, replacing unbounded activity membership computation. Activity sensor sample broadens time-filter upper bound to coalesce(ended_at, started_at + INTERVAL 12 HOUR). Tests verify bounded_activity_graph() invocation and absence of previous source('analytics', ...) references.
Worker entrypoint decoupled from analytics dbt builds
entrypoint.sh, analytics/models/read_models/read_model_microbatch.sql.test.ts
Worker mode no longer invokes dbt build before launching worker process, preventing worker restarts from being blocked by analytics builds. Test asserts worker path does not contain "dbt build".

Weekly Report Backend and Frontend Updates

Layer / File(s) Summary
Weekly report aggregation backend: Sunday weeks, null handling
packages/server/src/repositories/weekly-report-repository.ts, packages/server/src/routers/weekly-report.ts, packages/server/src/routers/weekly-report.test.ts
Switches aggregation from ISO Monday (toMonday()) to Sunday-start weeks (toStartOfWeek(..., 0)). Changes daily training load to sumIf(..., IS NOT NULL) to exclude null loads at daily level. Normalizes resting HR/HRV averages via avg(nullIf(..., 0)) to treat zeros as missing. Simplifies result selection to always return most recent week as current. Tests verify query structure, week boundaries, and null-handling behavior.
Weekly report card UI: no training vs sleep not tracked distinction
packages/web/src/components/WeeklyReportCard.tsx, packages/web/src/components/WeeklyReportCard.test.tsx
Adds hasTraining flag to distinguish "no training" (sleep tracked but no training) from "sleep not tracked" (no sleep). Status pill now renders three cases: sleep not tracked, no training, or strain-zone label. History mini-bar and "this week" segment require both sleep and training data for valid zone display. Tooltips/titles report correct missing-data state.

Integration Test and Incident Documentation

Layer / File(s) Summary
Ultrahuman sync integration test timer control
src/providers/ultrahuman-sync.integration.test.ts
Enables Vitest fake timers at fixed UTC timestamp before sync tests and restores real timers after completion, ensuring deterministic timer-dependent code behavior.
Production incident documentation
docs/production-incident-baseline.md
Records 2026-05-26/27 OOM incident: unbounded recursive activity graph in dbt builds combined with worker entrypoint coupling caused ClickHouse memory exhaustion. Documents symptoms, root cause, interim mitigation, code fix (this PR), and remaining validation work.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Multi-layer change with new macro logic (connected components, priority selection), refactoring of analytics models, backend aggregation logic migration (week boundary semantics), UI state handling, and deployment/architecture changes (entrypoint decoupling). Requires verification of ClickHouse query correctness, null-handling edge cases, and week boundary computation across multiple time-zone-aware functions.

Possibly related PRs

  • Asherlc/dofek#1185: Modifies the same analytics read models (activity_sensor_sample.sql, activity_location_sample.sql) for microbatch-bounded activity derivation.
  • Asherlc/dofek#1118: Implements overlapping activity deduplication and canonical selection using provider/device priority and connected components logic (precursor pattern to bounded macro approach).
  • Asherlc/dofek#1180: Introduced dbt build wiring into entrypoint.sh and analytics-worker; this PR removes that coupling.

Suggested labels

area/server, area/web, area/providers, type/bug

Suggested reviewers

  • cubic-dev-ai
🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning Title is in imperative mood, 52 characters, under 70 chars, and contains no trailing punctuation. However, it lacks an area prefix (e.g., [server], [analytics]) despite touching multiple areas. Add area prefix to clarify scope. Suggested: '[server] Fix weekly reports and analytics worker microbatches' or split into focused changes with appropriate prefixes per area requirement.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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 addresses correctness and stability issues in weekly performance reporting and ClickHouse-backed analytics microbatches, including decoupling the BullMQ worker startup from analytics dbt builds to avoid worker restart loops during dbt/ClickHouse OOM scenarios.

Changes:

  • Update weekly report aggregation and UI behavior for Sunday-start weeks and no-training/sleep edge cases.
  • Bound analytics activity graph construction to each dbt microbatch window and stop running dbt build in the worker entrypoint path.
  • Stabilize Ultrahuman integration tests by pinning the system clock to the asserted fixture date.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/providers/ultrahuman-sync.integration.test.ts Pins Vitest fake Date to make the integration test deterministic across real-time days.
packages/web/src/components/WeeklyReportCard.tsx Adds “No training” state and refines zone display logic for weeks without training/sleep data.
packages/web/src/components/WeeklyReportCard.test.tsx Adds coverage for the new “No training” UI state.
packages/server/src/routers/weekly-report.ts Adjusts weekly report ClickHouse query logic (week bucketing, load/vitals edge cases) and simplifies current/history selection.
packages/server/src/routers/weekly-report.test.ts Updates/extends router tests to assert new weekly bucketing/load/vitals behavior.
packages/server/src/repositories/weekly-report-repository.ts Mirrors weekly report query changes in repository implementation.
entrypoint.sh Removes dbt build from the worker mode so BullMQ worker startup isn’t blocked by analytics builds.
docs/production-incident-baseline.md Documents the production incident motivating the decoupling/bounding changes.
analytics/models/sources.yml Adds missing dbt sources needed by the bounded activity graph macro (device/provider priority).
analytics/models/read_models/read_model_microbatch.sql.test.ts Adds assertions for worker/dbt decoupling and bounded activity graph usage in microbatch models.
analytics/models/read_models/activity_sensor_sample.sql Switches to bounded recursive activity graph CTEs instead of global views.
analytics/models/read_models/activity_location_sample.sql Switches to bounded recursive activity graph CTEs instead of global views.
analytics/macros/bounded_activity_graph.sql Introduces a bounded recursive activity graph macro keyed to dbt microbatch start/end.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/server/src/routers/weekly-report.ts
Comment thread packages/server/src/repositories/weekly-report-repository.ts
Comment thread packages/server/src/routers/weekly-report.test.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 13 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: These changes include modifications to weekly report SQL logic (week boundaries, null handling, activity counting), a new 206-line dbt macro for bounded activity graphs, and UI logic for training status—core business logic with moderate blast radius that warrants human review.

Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 3 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread packages/server/src/repositories/weekly-report-repository.ts Outdated
Comment thread packages/server/src/routers/weekly-report.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@analytics/macros/bounded_activity_graph.sql`:
- Around line 158-166: The merged CTE currently uses the highest-priority
member's times (any(best.started_at)/any(best.ended_at)) which can narrow the
group's true time range; replace those with group-wide bounds so
current_activity.started_at/ended_at reflect the full merged component
timeframe. Concretely, in the merged AS select (and the second occurrence later
in the file) change the time columns to use min(best.started_at) AS started_at
and max(best.ended_at) AS ended_at (instead of any(...)) so downstream joins in
activity_sensor_sample.sql include all edge samples for the merged activity.
- Around line 80-94: The overlap calculation uses a 1-hour fallback for NULL
ended_at which is inconsistent with active_activity and
activity_sensor_sample.sql that use a 12-hour window; update the two occurrences
of coalesce(..., started_at + INTERVAL 1 HOUR) (both for left_activity and
right_activity in the greatest/least expressions, numerator and denominator) to
use INTERVAL 12 HOUR so NULL-ended activities are treated as started_at + 12
hours for overlap computation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3587250d-428b-435c-a556-8551c63f252c

📥 Commits

Reviewing files that changed from the base of the PR and between 9f8a341 and 09b94b9.

📒 Files selected for processing (13)
  • analytics/macros/bounded_activity_graph.sql
  • analytics/models/read_models/activity_location_sample.sql
  • analytics/models/read_models/activity_sensor_sample.sql
  • analytics/models/read_models/read_model_microbatch.sql.test.ts
  • analytics/models/sources.yml
  • docs/production-incident-baseline.md
  • entrypoint.sh
  • packages/server/src/repositories/weekly-report-repository.ts
  • packages/server/src/routers/weekly-report.test.ts
  • packages/server/src/routers/weekly-report.ts
  • packages/web/src/components/WeeklyReportCard.test.tsx
  • packages/web/src/components/WeeklyReportCard.tsx
  • src/providers/ultrahuman-sync.integration.test.ts
💤 Files with no reviewable changes (1)
  • entrypoint.sh

Comment thread analytics/macros/bounded_activity_graph.sql
Comment thread analytics/macros/bounded_activity_graph.sql Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

0 issues found across 3 files (changes from recent commits).

Auto-approved: This PR fixes a production incident by bounding activity graph construction to microbatch windows to prevent ClickHouse OOMs, decouples the BullMQ worker from dbt builds, corrects weekly report week bucketing and training load aggregation, and adds corresponding tests—all changes are...

Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Requires human review: The changes touch core business logic (weekly report SQL bucketing, training load math), analytics pipeline (new bounded activity macro replacing global views), and infrastructure (entrypoint removal of dbt from worker), which have significant blast radius and risk of breaking production data...

Re-trigger cubic

…alth-summary

# Conflicts:
#	docs/production-incident-baseline.md
@github-actions

Copy link
Copy Markdown
Contributor

Storybook previews for fd1acac4 are ready:

This comment updates automatically on each PR push.

@Asherlc
Asherlc enabled auto-merge (squash) May 27, 2026 02:21
@Asherlc
Asherlc merged commit e7e7399 into main May 27, 2026
65 of 66 checks passed
@Asherlc
Asherlc deleted the Asherlc/fix-weekly-health-summary branch May 27, 2026 02:21
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