fix(auto): log empty auto-family pools once per process (#10820)

Merged — validated together with a batch of related RaviTharuma PRs in one combined worktree (typecheck:core clean, complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
This commit is contained in:
Ravi Tharuma
2026-08-20 16:48:03 +02:00
committed by GitHub
parent 77d75022d6
commit 2f7315882b
3 changed files with 20 additions and 15 deletions

View File

@@ -0,0 +1 @@
- **fix(backend):** log `auto/<family> matched no connected models` once per process per label instead of every minute ([#10346](https://github.com/diegosouzapw/OmniRoute/issues/10346))

View File

@@ -44,21 +44,19 @@ export interface AutoComboSpec {
family?: ModelFamily;
}
/** Rate-limit empty-pool AUTO warns (same label can be resolved many times/min). */
const emptyPoolWarnAt = new Map<string, number>();
export const EMPTY_POOL_WARN_INTERVAL_MS = 60_000;
/** Once-per-process empty-pool AUTO warns (steady empty is not a metronome). */
const emptyPoolWarned = new Set<string>();
export function warnEmptyAutoPoolOnce(label: string, message: string, now = Date.now()): boolean {
const last = emptyPoolWarnAt.get(label) ?? 0;
if (now - last < EMPTY_POOL_WARN_INTERVAL_MS) return false;
emptyPoolWarnAt.set(label, now);
export function warnEmptyAutoPoolOnce(label: string, message: string, _now = Date.now()): boolean {
if (emptyPoolWarned.has(label)) return false;
emptyPoolWarned.add(label);
log.warn("AUTO", message);
return true;
}
/** Test-only: reset the debounce map. */
/** Test-only: reset the once-per-label set (also models emptiness reappearing). */
export function resetEmptyAutoPoolWarnStateForTests(): void {
emptyPoolWarnAt.clear();
emptyPoolWarned.clear();
}
/** Minimal connection shape needed for virtual auto-combo factory */

View File

@@ -1,18 +1,24 @@
import test from "node:test";
import assert from "node:assert/strict";
import { test } from "node:test";
import {
EMPTY_POOL_WARN_INTERVAL_MS,
resetEmptyAutoPoolWarnStateForTests,
warnEmptyAutoPoolOnce,
} from "../../open-sse/services/autoCombo/virtualFactory.ts";
test("warnEmptyAutoPoolOnce emits at most once per label per interval", () => {
test("warnEmptyAutoPoolOnce emits at most once per label per process", () => {
resetEmptyAutoPoolWarnStateForTests();
const t0 = 1_000_000;
const t0 = 1_700_000_000_000;
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0), true);
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0 + 1), false);
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0 + EMPTY_POOL_WARN_INTERVAL_MS - 1), false);
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0 + 60_000), false);
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0 + 3_600_000), false);
assert.equal(warnEmptyAutoPoolOnce("auto/other", "empty", t0 + 1), true);
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0 + EMPTY_POOL_WARN_INTERVAL_MS), true);
});
test("resetEmptyAutoPoolWarnStateForTests allows a later warn (emptiness reappeared)", () => {
resetEmptyAutoPoolWarnStateForTests();
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty"), true);
resetEmptyAutoPoolWarnStateForTests();
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty"), true);
});