mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 12:22:34 +03:00
fix(ci): clear five uncovered base-reds on release/v3.8.51 — auto-combo catalog event-loop pin, unweighted quota-share, resilience key set, pack-gate stamp, synced-catalog env doc (#13678)
* fix(combo): rotate unweighted quota-share targets instead of pinning the first The combo resolver turns an unset step weight into 0 (comboStructure.ts), and #10881 made normalizeWeight treat 0 as disabled plus return definition order when the total weight is 0. A quota-share combo without explicit weights therefore had no DRR quanta and dispatched every request to its first target — the combo-matrix/quota-share integration suite saw openai six times out of six. An all-zero set is now an unweighted combo and shares evenly; an explicit 0 still disables a target when its siblings are weighted. Refs #12732 * fix(models): resolve auto-combo target metadata once per catalog build #12046 derives vision/modalities for the built-in auto/* combos by resolving catalog metadata for every target of every combo. The ~40 auto combos share one candidate pool and the loop neither memoized nor yielded, so the #9147 fixture (60 connections, 720 synced models) went from a ~4s build with a 167ms longest event-loop gap to ~11s and a 860-1070ms gap on an idle box — past the 800ms contract and past #12628's 8s cold-build bound, which is why the test came back 500 catalog_build_timeout on every release-green run. Metadata depends only on the target's provider/model/connection scope within a build, so memoize it per build and yield between misses. Same fixture: 2.3-3.1s build, 56-72ms longest gap. The 9147 test is unchanged. Refs #12732 * test(resilience): list credentialHealthCheck in the configuration-only key set #12043 added credentialHealthCheck.intervalMinutes to DEFAULT_RESILIENCE_SETTINGS and to the /api/resilience GET projection. It is operator configuration (the background sweep cadence), not runtime breaker state, but the exact key-set assertion was never updated, so resilience-http-e2e failed on the release tip. The providerBreakers/runtime absence checks stay as they were. Refs #12732 * fix(ci): stamp BUILD_SHA before the release-green pack gate validates check:pack-artifact assembles dist/ through build:cli, which never writes dist/BUILD_SHA (only build:release does). #12959 pointed the provenance ref at HEAD, but the #10427 guard still stops at 'dist/BUILD_SHA is missing' before it ever reaches the ancestry check — reproduced on tip + #13635 + #13436, the first tree whose Turbopack build compiles. ci.yml sequences build -> stamp -> validate; the validator now does the same in both entry points, keeping PACK_GATE_ENV for the validate step. The guard is unchanged: an unstamped dist/ or one built from another commit still fails. On that tree the stamped gate passes: 'BUILD_SHA 5cb3ae5d9 is on the release line'. Refs #12732 * docs(env): document OMNIROUTE_SYNCED_CATALOG_STALE_AFTER_MS #13248 (#12849) added the override for when a connection's synced model list stops being authoritative, but neither .env.example nor ENVIRONMENT.md lists it, so the env/docs contract gate reports it as code-only. The other five vars that gate reports are already added by #13635 and #13361; this touches a different region of .env.example so it does not collide with either. Refs #12732
This commit is contained in:
committed by
GitHub
parent
9442bdef0f
commit
d36251cf1c
@@ -104,6 +104,7 @@ import {
|
||||
mergeComboCapabilities,
|
||||
getConnectionScopedEffortTiers,
|
||||
type ConnectionScopedReasoningCatalog,
|
||||
memoizeTargetMetadata,
|
||||
} from "./catalogHelpers";
|
||||
import {
|
||||
qualifyOpenRouterModelId,
|
||||
@@ -848,6 +849,7 @@ async function buildUnifiedModelsResponseCore(
|
||||
// catalog build. Runtime auto routing still prepares fresh request-scoped inputs.
|
||||
let preparedAutoInputs: Awaited<ReturnType<typeof prepareBuiltinAutoComboInputs>> | undefined;
|
||||
let materializedAutoCount = 0;
|
||||
const autoMeta = memoizeTargetMetadata(getComboTargetCatalogMetadata, maybeYieldCatalogBuild);
|
||||
for (const autoId of [
|
||||
...Object.keys(AUTO_TEMPLATE_VARIANTS),
|
||||
...AUTO_SUFFIX_VARIANTS,
|
||||
@@ -890,7 +892,7 @@ async function buildUnifiedModelsResponseCore(
|
||||
connectionId: m.connectionId,
|
||||
...(m.allowedConnectionIds ? { allowedConnectionIds: m.allowedConnectionIds } : {}),
|
||||
}));
|
||||
const autoTargetMetadata = autoTargets.map((t) => getComboTargetCatalogMetadata(t));
|
||||
const autoTargetMetadata = await autoMeta(autoTargets); // #9147: once per build
|
||||
const knownAutoMeta = autoTargetMetadata.filter(
|
||||
(m): m is ComboTargetCatalogMetadata => m !== null
|
||||
);
|
||||
|
||||
@@ -222,3 +222,36 @@ export function mergeComboCapabilities(
|
||||
}
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Memoize per-target catalog metadata for one catalog build, yielding between misses.
|
||||
* #12046 resolves metadata for every target of every built-in `auto/*` combo, and those
|
||||
* ~40 combos draw on the same candidate pool: unmemoized, the build repeated the same
|
||||
* lookups tens of thousands of times without yielding (#9147 — 720 synced models took the
|
||||
* cold build from ~4s to ~18s, past the 8s cold-build bound). Metadata depends only on
|
||||
* the target fields in the key, so each distinct target is resolved once per build.
|
||||
*/
|
||||
export function memoizeTargetMetadata<T>(
|
||||
resolve: (target: ComboCatalogTarget) => T | null,
|
||||
afterMiss: () => Promise<void>
|
||||
): (targets: ComboCatalogTarget[]) => Promise<Array<T | null>> {
|
||||
const byKey = new Map<string, T | null>();
|
||||
return async (targets) => {
|
||||
const resolved: Array<T | null> = [];
|
||||
for (const target of targets) {
|
||||
const key = JSON.stringify([
|
||||
target.providerId ?? null,
|
||||
target.provider ?? null,
|
||||
target.modelStr ?? null,
|
||||
target.connectionId ?? null,
|
||||
target.allowedConnectionIds ?? null,
|
||||
]);
|
||||
if (!byKey.has(key)) {
|
||||
byKey.set(key, resolve(target));
|
||||
await afterMiss();
|
||||
}
|
||||
resolved.push(byKey.get(key) ?? null);
|
||||
}
|
||||
return resolved;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user