Compare commits

...

1 Commits

Author SHA1 Message Date
Eve
47a5a63178 fix(runtimes): narrow CostCell usage window from 180d to 14d
The runtimes list page renders a CostCell per row that only displays a
7d cost total plus a 7d-vs-prior-7d delta. Until now each cell still
fetched a 180d usage window so the cache key matched the runtime-detail
page (clicking a row would pre-warm detail). The side effect was N
parallel 180d in-line aggregations against task_usage on every list
visit, one per runtime, which dominated DB load for this view.

Switch the cell to a 14d window — exactly the data it actually needs
for cost7d + costPrev7d. Detail still owns its own 180d query; the
worst case after this change is one extra request on first navigation
into detail, in exchange for a large steady-state reduction on the
list page (down to 14d × N instead of 180d × N, ~13× fewer rows
scanned per request).

This is the frontend half of the runtime-usage perf work tracked in
MUL-1748. The backend index + daily rollup changes will land
separately.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-05-06 13:38:41 +08:00

View File

@@ -51,8 +51,8 @@ import {
// Per-row data assembled at the page level. The columns reach into
// `row.original` and never pull their own data — except for the per-runtime
// usage query in CostCell, which intentionally keeps its 180-day cache key
// shared with the runtime-detail page (clicking a row pre-warms detail).
// usage query in CostCell, which fetches its own narrow 14-day window
// (just enough for the cell's 7d cost + 7d prior-window delta).
export interface RuntimeRow {
runtime: AgentRuntime;
ownerMember: MemberWithUser | null;
@@ -320,12 +320,20 @@ function WorkloadCell({
);
}
// Per-row cost — fetches the same 180-day usage window used by the
// runtime-detail page so clicking a row makes detail render instantly from
// cache. Cold load incurs N parallel requests, but each is cheap and they
// all share the same query key.
// Per-row cost — only renders a 7d total + delta vs the prior 7d, so we
// only need 14 days of usage. Previously this fetched a 180-day window to
// share the cache key with the runtime-detail page, but that turned the
// list page into N × 180d in-line aggregations against `task_usage` (one
// per runtime row) and dominated DB load for this view. Detail still
// fetches its own 180d window on navigation; the cold-load difference for
// detail is one extra request, while the steady-state savings on the list
// page are large.
const COST_CELL_DAYS = 14;
function CostCell({ runtimeId }: { runtimeId: string }) {
const { data: usage = [] } = useQuery(runtimeUsageOptions(runtimeId, 180));
const { data: usage = [] } = useQuery(
runtimeUsageOptions(runtimeId, COST_CELL_DAYS),
);
const cost7d = useMemo(() => computeCostInWindow(usage, 7), [usage]);
const costPrev7d = useMemo(
() => computeCostInWindow(usage, 7, 7),