Repository navigation
fix: improve performance for history charts - #169
Conversation
- api: memoize past-day energy totals on the Server; only today is
recomputed per request. Past days are immutable once the day ends.
- state: new DailyEnergy() integrates grid/pv/bat/load via a SQL LAG()
window — one row returned per day instead of shipping ~17k hot-tier
samples to Go. Weekly/monthly dashboards go from seconds to tens of ms.
- state: BulkRecordHistory() wraps many inserts in one transaction;
CountNonSyntheticHistory() counts rows missing the backfill JSON
marker — the safety gate for the dev seeder.
- cli: -backfill N / -backfill-step / -backfill-seed / -backfill-force
on the main forty-two-watts binary. Seeds N days of diurnal synthetic
history into state.db then exits. Refuses if the DB already holds
non-synthetic rows (production-safety gate).
- devtools: reusable generator with per-day weather + household profiles
keyed on date^seed, AR(1) coloured noise on PV/load, rare appliance
and cloud-shadow events. Stamps every row with {"source":"backfill"}
so the safety gate can recognise its own output.
- skill: .claude/skills/dev-backfill documents invocation + the
safety-gate semantics for future sessions.
- .gitignore: dev-data/ playground + per-user settings.local.json.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ellow toggle - ftw-energy-flow: migrate from the 5-box hero to the planet/sun layout (HOUSE at centre, 45° corners with clustering). Dynamic SVG height grows with the largest cluster, desktop defaults bumped ~20% so the hero reads as the focal point on large screens. - theme.css: new --fg-label token (dark: oklch(0.86); light: mirrors --fg-dim). Hero bubble labels pulled up to the same brightness so the gray "SOLAR / BATTERY / GRID / EV CHARGER" text stops feeling dim. - next.css: every .card-label (summary, fuse, history, energy, control) adopts --fg-label. Desktop (≥901 px) bumps label size 10 → 12 px. history-toggle Week/Month pill — active state now --amber on --ink (our yellow); deselected --fg-label so inactive text matches the other labels instead of being dimmer. - next-app.js, index.html: wiring / markup updates that accompany the hero redesign and the per-EV planet popups (daily kWh stats cards). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves the /next dashboard’s perceived performance and UX by replacing heavy history-chart rendering with lightweight daily “history cards”, and by pushing daily energy aggregation into SQLite with caching and dev tooling to backfill data.
Changes:
- Add
/api/energy/dailybacked by SQL-side integration (Store.DailyEnergy) plus per-day server caching. - Update
/nextUI to render daily history cards and refactor the hero energy-flow into a generic “planets” model (including EV modal opened from the hero). - Add a dev-only
-backfillCLI path to seed synthetic history intostate.dbfor local UI/perf work.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| web/next.css | Adds layout/typography updates and styling for new history cards + fuse layout. |
| web/next-app.js | Builds hero “planets”, moves EV modal trigger to hero, and adds history-cards fetching/rendering. |
| web/index.html | Reworks the /next card layout (history cards + fuse row; removes SoC/EV tiles). |
| web/components/theme.css | Introduces --fg-label and brightens hero label/sub text tokens. |
| web/components/ftw-energy-flow.js | Refactors hero diagram to accept a planet list, adds dynamic sizing + clickable planets. |
| go/internal/state/store.go | Adds bulk insert for backfill + SQL-integrated daily energy aggregation + safety-gate query. |
| go/internal/devtools/backfill.go | Adds synthetic history backfill utility (flag-invoked). |
| go/internal/api/api.go | Adds /api/energy/daily endpoint and a process-lifetime cache for past days. |
| go/cmd/forty-two-watts/main.go | Wires -backfill* flags to run the dev backfill and exit. |
| .gitignore | Ignores dev-data/ and local Claude settings file. |
| .claude/skills/dev-backfill/SKILL.md | Documents the new dev backfill workflow and safety gate. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <div class="history-toggle" role="tablist"> | ||
| <button data-range="week" class="active" role="tab">Week</button> | ||
| <button data-range="month" role="tab">Month</button> | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
The history range toggle uses role="tablist"/role="tab" but doesn’t implement required tab semantics (aria-selected, roving tabindex, arrow-key navigation, associated tabpanels). This is misleading for assistive tech. Either implement full tabs behavior or simplify to regular buttons (e.g., remove the tab roles and use aria-pressed / visually-active state).
| return ` | ||
| <div class="title">Energy balance</div> | ||
| <svg viewBox="${P.vbX} 0 ${P.vbW} ${H}" preserveAspectRatio="xMidYMid meet" aria-hidden="true"> | ||
| <svg viewBox="${P.vbX} 0 ${P.vbW} ${P.H}" preserveAspectRatio="xMidYMid meet" aria-hidden="true"> |
There was a problem hiding this comment.
The SVG is marked aria-hidden="true" while containing keyboard-focusable, clickable planets (tabindex=0 + keydown handler). Interactive elements inside an aria-hidden subtree are inaccessible/invalid for assistive tech. Consider removing aria-hidden on the SVG (or moving interactivity outside), and add appropriate roles/labels (e.g., role="button" + aria-label) for clickable planets.
| <svg viewBox="${P.vbX} 0 ${P.vbW} ${P.H}" preserveAspectRatio="xMidYMid meet" aria-hidden="true"> | |
| <svg viewBox="${P.vbX} 0 ${P.vbW} ${P.H}" preserveAspectRatio="xMidYMid meet"> |
Master has since landed the history-cards feature set (per-metric web components in ftw-history-card.js, ftw-bar-chart.js) and the /api/energy/daily endpoint with proper error handling and tier-deduped LoadHistory — superseding most of this branch's web/api changes. Resolution: take master's versions for the five conflicting UI/api files (ftw-energy-flow.js, index.html, next-app.js, next.css, api.go). The PR retains its unique contribution — the dev-only state.db backfill tool plus the BulkRecordHistory / CountNonSyntheticHistory helpers it needs. Also drops the now-orphaned state.DailyEnergy / state.DayEnergy (master's handleEnergyDaily uses LoadHistory, which already dedupes tiers) and fixes the backfill marker "round-trip" sanity check in devtools/backfill.go to actually Marshal after Unmarshal and compare (addressing Copilot review comment #7 on PR #169). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…merge PR #169 (feat/history-perf-and-dev-backfill) described "weekly/monthly dashboards go from seconds to tens of ms" but the merge commit 02146c9 "Merge master into feat/history-perf-and-dev-backfill" explicitly dropped state.DailyEnergy / DayEnergy as "now-orphaned", leaving the naïve LoadHistory-based handler on master. Measured on a live site today: /api/energy/daily?days=7 → 1.6 s, days=30 → 1.8 s, days=90 → 3.4 s — exactly the "seconds" the original commit claimed to eliminate. Restoring the two missing pieces from 8c0771f: - state.DayEnergy + DailyEnergy(sinceMs, untilMs): one round-trip that integrates grid/pv/bat/load via a SQL LAG() window across the three-tier UNION, returning a single pre-integrated row instead of shipping ~17k hot-tier samples per day to Go. - Server.dailyCache + dailyCacheMu: per-local-day memo keyed by "YYYY-MM-DD". Past days are immutable once the day ends, so only today recomputes per request. handleEnergyDaily now walks day-by-day: cache-hit for closed days, always-recompute for today, early-return 500 on the first DB error (keeps the existing TestHandleEnergyDailyReturns500OnDBError contract). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
No description provided.