// One continuity policy for all browser-side counter-derived rates. // Background tabs cannot supply a valid instantaneous rate for an interval // spanning the pause. Keep the plotted history and rebase on the next sample. const rustProxyRateSampling = (() => { let generation = 0; const pause = () => { generation += 1; }; document.addEventListener?.("visibilitychange", () => { if (document.hidden) pause(); }); window.addEventListener?.("pagehide", pause); function cadence(key) { const value = window.rustProxyRefresh?.current?.()?.[key]; const fallback = key === "cache_seconds" ? 5 : 3; return Number.isFinite(value) && value > 0 ? value : fallback; } function stamp(at) { return { at, generation }; } function continuous(previous, at, intervalSeconds = 3) { const seconds = Number.isFinite(intervalSeconds) && intervalSeconds > 0 ? intervalSeconds : 3; return Boolean(previous && !document.hidden && previous.generation === generation && Number.isFinite(at) && Number.isFinite(previous.at) && at > previous.at && at - previous.at <= Math.max(10000, seconds * 3000)); } function difference(previous, values, at, intervalSeconds = 3) { const next = { ...stamp(at), values: [...values] }; if (!continuous(previous, at, intervalSeconds) || values.some((value, i) => !Number.isFinite(value) || value < 0 || !Number.isFinite(previous.values[i]) || value < previous.values[i])) { return { next, deltas: null, seconds: null }; } return { next, deltas: values.map((value, i) => value - previous.values[i]), seconds: (at - previous.at) / 1000 }; } return { cadence, stamp, continuous, difference }; })();