Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fixes/auto-empty-pool-log-once.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(auto):** rate-limit `auto/<family> matched no connected models` warnings to once per minute per label (`open-sse/services/autoCombo/virtualFactory.ts`)
21 changes: 19 additions & 2 deletions open-sse/services/autoCombo/virtualFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ 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;

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);
log.warn("AUTO", message);
return true;
}

/** Test-only: reset the debounce map. */
export function resetEmptyAutoPoolWarnStateForTests(): void {
emptyPoolWarnAt.clear();
}

/** Minimal connection shape needed for virtual auto-combo factory */
interface VirtualFactoryConn extends ConnectionFields {
id: string;
Expand Down Expand Up @@ -665,8 +682,8 @@ export async function createVirtualAutoComboFromPrepared(
// Family combos always degrade to an empty pool when unavailable — a family
// is a hard identity constraint, not a soft optimization bias, so there is
// no sensible "fall back to the full pool" behavior for it.
log.warn(
"AUTO",
warnEmptyAutoPoolOnce(
label,
`${label} matched no connected models; returning an empty pool.${spec?.family ? "" : ' Set OMNIROUTE_AUTO_FREE_FALLBACK_TO_FULL_POOL=true to restore the legacy "use full pool" behavior.'}`
);
effectivePool = [];
Expand Down
18 changes: 18 additions & 0 deletions tests/unit/auto-empty-pool-warn-once.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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", () => {
resetEmptyAutoPoolWarnStateForTests();
const t0 = 1_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/other", "empty", t0 + 1), true);
assert.equal(warnEmptyAutoPoolOnce("auto/zai", "empty", t0 + EMPTY_POOL_WARN_INTERVAL_MS), true);
});
Loading