Skip to content

Commit e59f65a

Browse files
committed
fix(webapp): take the queue metric day budget exactly as the plan gives it
Rounding the plan's query period up to a whole day would have let these pages read further back than every other metric query for a sub-day limit. The budget is now used as-is, matching the bound executeQuery enforces, and the period string derived from it steps down to hours or minutes so a fractional budget still yields a window inside it.
1 parent bece64f commit e59f65a

2 files changed

Lines changed: 19 additions & 7 deletions

File tree

apps/webapp/app/components/queues/queueMetricsPeriod.server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { QUEUE_METRICS_RETENTION_DAYS } from "./queueMetricsPeriod";
77
* and go straight to ClickHouse stay in step with the ones that don't.
88
*
99
* Read through the limit cache: the queues page revalidates on an interval, so this runs far more
10-
* often than a one-off page load. Whole days keep the derived period string well formed.
10+
* often than a one-off page load.
1111
*/
1212
export async function queueMetricsMaxPeriodDays(organizationId: string): Promise<number> {
1313
const cached = await getCachedLimit(
@@ -16,5 +16,5 @@ export async function queueMetricsMaxPeriodDays(organizationId: string): Promise
1616
QUEUE_METRICS_RETENTION_DAYS
1717
);
1818
const planPeriodDays = cached.val ?? QUEUE_METRICS_RETENTION_DAYS;
19-
return Math.max(1, Math.min(Math.floor(planPeriodDays), QUEUE_METRICS_RETENTION_DAYS));
19+
return Math.min(planPeriodDays, QUEUE_METRICS_RETENTION_DAYS);
2020
}

apps/webapp/app/components/queues/queueMetricsPeriod.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ const PERIOD_PATTERN = /^\d+[mhd]$/;
2525
/** Queue metrics are retained for 30 days, so a longer window can only ever render empty. */
2626
export const QUEUE_METRICS_RETENTION_DAYS = 30;
2727

28-
const DAY_MS = 24 * 60 * 60 * 1000;
28+
const MINUTE_MS = 60 * 1000;
29+
const HOUR_MS = 60 * MINUTE_MS;
30+
const DAY_MS = 24 * HOUR_MS;
2931
const MAX_PERIOD_MS = QUEUE_METRICS_RETENTION_DAYS * DAY_MS;
3032

3133
function isPeriod(value: string | undefined | null): value is string {
@@ -90,13 +92,23 @@ export function resolveQueueMetricsPeriod({
9092
}
9193

9294
/**
93-
* Hold a period inside a day budget (the org's plan query period). A remembered period longer than
94-
* the plan allows becomes the plan's maximum, so the picker shows the window the data covers.
95+
* Hold a period inside a day budget (the org's plan query period). A period longer than the plan
96+
* allows becomes the plan's maximum, so the picker shows the window the data covers.
97+
*
98+
* The budget is whatever the plan says, not necessarily a whole number of days, so the replacement
99+
* is expressed in the largest unit that divides it: rounding down keeps the period inside the
100+
* budget rather than a hair over it.
95101
*/
96102
export function clampQueueMetricsPeriod(period: string, maxPeriodDays: number): string {
103+
const maxMs = maxPeriodDays * DAY_MS;
97104
const ms = parse(period);
98-
if (typeof ms === "number" && ms > 0 && ms <= maxPeriodDays * DAY_MS) return period;
99-
return `${maxPeriodDays}d`;
105+
if (typeof ms === "number" && ms > 0 && ms <= maxMs) return period;
106+
107+
const days = Math.floor(maxMs / DAY_MS);
108+
if (days >= 1) return `${days}d`;
109+
const hours = Math.floor(maxMs / HOUR_MS);
110+
if (hours >= 1) return `${hours}h`;
111+
return `${Math.max(1, Math.floor(maxMs / MINUTE_MS))}m`;
100112
}
101113

102114
/**

0 commit comments

Comments
 (0)