Repository navigation
feat(web): redesign the pages and keep reads responsive during index rebuilds - #3
Merged
Merged
Conversation
A price book change or a new account forces a full report index rebuild. On the NAS that took over three minutes on the report worker, and every page request queued behind it. The rebuild now runs in a separate builder thread into side files while the worker keeps answering from the previous index. Those answers are marked as refreshing and labeled with the price version they were computed with. The files are swapped when the build completes and every cached view is refreshed. A replaced ledger or a different price book identity still rebuilds inline, so old results never cross those boundaries. A full rebuild also drops and recreates the secondary indexes around the bulk insert, which is about 30% faster on the production snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
The bundled book moves to 2026-09-25.2 with GPT-6 Sol and GPT-6 Luna at the rates OpenAI published on 2026-09-22. No existing OpenAI rate changed. It also declares that it supersedes meterleaf-openai, the id used through 0.2.1, so cached report views survive the upgrade instead of being thrown away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
A first build, a replaced ledger, an unrelated price book or a failed background build used to rebuild inline and hold every query. Reads now show the previous index whenever it belongs to the same ledger, and otherwise answer 202 building so the page shows progress and polls. The builder switches its files out of WAL before closing, because the macOS system SQLite keeps WAL files on close and the swap was silently falling back to an inline rebuild there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
Accounts can be renamed inside Meterleaf without touching the upstream. Plan badges align by usage multiple across Claude and ChatGPT, using the upstream platform to tell Claude Pro apart from ChatGPT Pro 20x. The collector names its account "Claude Code" and model colors no longer collide. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
The Web and PWA pages follow the accepted redesign. Neutral grays replace the tinted backgrounds, numbers use Geist, and the palette option offers brand green, indigo or mono independent of light and dark. Charts read the active theme colors instead of a dark flag. The overview becomes a ledger strip plus one account list that shares the accounts page row, with the 7d estimate drawn as a line. The Credits card appears only when there is Credits usage, and an expired quota snapshot shows its last sample time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
The 7d estimate column stacks its label, a short line and the amount without a caption, and an account without a valid quota shows one dashed note across the quota columns. The overview tabs keep equal widths and the same offset on both views. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
A five-hour window that expired or lost its value used to disappear until the next sample, so it flickered with the collection cadence. While the weekly quota is valid and not used up, the slot stays and says it is waiting for a new sample, without old percentages or costs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
Trend series only carry buckets that had requests, so quiet hours and days collapsed on the axis. Charts now add zero buckets between the first and last reported ones. Time outside that span stays absent because the ledger may not cover it. Account rows also give the name column the width of the design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
Behind an authentication gateway an expired session redirected ledger reads to the login page, which surfaced as a network failure and a broken brand icon. Ledger reads now follow redirects manually, show a re-login prompt without retrying, and the service worker precaches the brand icon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
The sync panel showed stage codes and an error id that readers could not act on. It now names the step that failed and what to check, and the id stays in the server log. The green palette is renamed 翠绿 to match the other two-character names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
The tooltip of a mini trend was confined to a chart a few dozen pixels tall and clipped by its card. It now renders on the page body with the time and value on separate lines. The expired quota note is shorter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
Between 1001 and 1250px the base two-row areas and the desktop five-column grid applied together, squeezing accounts with two quota windows into the left half. These rows now use the two-row layout up to 1250px with the menu in the top corner, and the five-column row above. The docs describe the overview showing lifetime usage first for accounts without a quota. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
The smoke, layout, sync and quota specs asserted the old overview cards, colors and sync error ids. They now check the shared account rows, the waiting five-hour slot, plain sync failure text and that quota rows keep one header line at desktop widths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
9D17
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这个 PR 包含三部分,报表后台重建、计价与账户显示、Web 界面重新设计。NAS 已运行本分支最新提交的候选镜像。
报表后台重建
问题
升级到含 Claude 价格的版本后,NAS 上的页面卡了三分多钟。日志显示,第一次查询在报表线程里全量重建索引,用了 199 秒(
report.index_updated initial=true durationMs=199337),其余页面请求全部排在后面,最多等了 124 秒。有两个原因叠加:
meterleaf-openai改为meterleaf,页面缓存按标识分区,结果整个被清空,连已经打开过的页面也只能等重建。变化
supersedes字段。内置价格表声明接替meterleaf-openai,从 0.2.x 升级时页面缓存保留。2026-09-25.2,加入 2026-09-22 发布的 GPT-6 Sol 与 GPT-6 Luna。其余 OpenAI 费率对照官方页面未变化。验证
bun run typecheck、bun test tests(298 pass)、bun run build、所改文件 Prettier 与git diff --check通过。两个提交各自可以单独通过类型检查与测试。在生产快照(25.5 万条用量)上模拟从 0.2.1 升级:
meterleaf-openai@2026-09-09.3meterleaf@2026-09-25.2生效修改前,同样的升级让首个请求阻塞 17.6 s。
全量重建(在已有索引上重建)从 18.8 s 降到 13.3 s。
NAS 实测(28.4 万条用量,候选镜像
1372e89):后台重建耗时 67.5 s,之前是 199 s。重建期间,默认视图响应 7–19 ms,从未缓存的日期范围 138–527 ms,均标注旧版本meterleaf@2026-09-25.1。替换后自动切换到2026-09-25.2。记录数与自动同步设置不变,无密钥推送仍返回 401。新增回归测试覆盖以下场景:
id的缓存按supersedes保留。已知限制
计价与账户显示
Web 界面重新设计
验证
bun run typecheck通过,bun test tests313 pass。新增continuous-points、session、sync-failure-message测试,更新quota-display、mobile-home、pwa测试。quota-pwa-layout(48 个状态,含 16 个双额度窗口和 3 个安全区状态)、browser.smoke、overview-account-usage通过,截图在已忽略的test-results。ff71c86(28.4 万条用量):后台索引重建 66.8 s,期间默认视图 9–15 ms、未缓存范围 154–507 ms。记录数与自动同步设置不变,无密钥推送返回 401。已知限制
mobile-app、visual-feedback、appearance-sorting、button-contrast、mobile-request-layout、pwa、account-management、report-preferences、sync-refresh。其中后三个需要先按新结构更新脚本。🤖 Generated with Claude Code
https://claude.ai/code/session_012bEAuLoXyJtm1PRMVvDi3z