fix(agent): consider the full fallback pool within the request deadline
This commit is contained in:
parent
bd27401b6c
commit
e3a8f0e0a1
@ -67,11 +67,9 @@ export function createAgentModelFailover(entries: AgentModelEntry[], circuit: Ag
|
|||||||
const totalSignal = signal ? AbortSignal.any([signal, deadline]) : deadline;
|
const totalSignal = signal ? AbortSignal.any([signal, deadline]) : deadline;
|
||||||
const ordered = [...entries].sort((a, b) => Number(b.model.id === preferred) - Number(a.model.id === preferred));
|
const ordered = [...entries].sort((a, b) => Number(b.model.id === preferred) - Number(a.model.id === preferred));
|
||||||
let last: unknown;
|
let last: unknown;
|
||||||
let attempts = 0;
|
|
||||||
for (const entry of ordered) {
|
for (const entry of ordered) {
|
||||||
totalSignal.throwIfAborted();
|
totalSignal.throwIfAborted();
|
||||||
if (await circuit.isPaused(entry)) continue;
|
if (await circuit.isPaused(entry)) continue;
|
||||||
if (attempts++ >= 4) break;
|
|
||||||
const attemptSignal = AbortSignal.any([totalSignal, AbortSignal.timeout(AGENT_MODEL_ATTEMPT_MS)]);
|
const attemptSignal = AbortSignal.any([totalSignal, AbortSignal.timeout(AGENT_MODEL_ATTEMPT_MS)]);
|
||||||
try {
|
try {
|
||||||
const result = await execute(entry, attemptSignal);
|
const result = await execute(entry, attemptSignal);
|
||||||
|
|||||||
@ -54,11 +54,14 @@ test("invalid input, content policy and cancellation neither quarantine nor retr
|
|||||||
assert.equal(s.faults.size, 0);
|
assert.equal(s.faults.size, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("multiple failed backups are skipped; no model is tried twice and attempts are bounded", async () => {
|
test("every eligible backup is considered once; a fixed small retry count cannot strand a healthy later model", async () => {
|
||||||
const s = store(); const calls: string[] = [];
|
const s = store(); const calls: string[] = [];
|
||||||
await assert.rejects(createAgentModelFailover(["a", "b", "c", "d", "e"].map(id => entry(id)), s.circuit)(async e => { calls.push(e.model.id); throw Object.assign(new Error("busy"), { status: 503 }); }));
|
await assert.rejects(createAgentModelFailover(["a", "b", "c", "d", "e"].map(id => entry(id)), s.circuit)(async e => { calls.push(e.model.id); throw Object.assign(new Error("busy"), { status: 503 }); }));
|
||||||
assert.deepEqual(calls, ["a", "b", "c", "d"]);
|
assert.deepEqual(calls, ["a", "b", "c", "d", "e"]);
|
||||||
assert.equal(s.faults.size, 4);
|
assert.equal(s.faults.size, 5);
|
||||||
|
calls.length = 0;
|
||||||
|
const result = await createAgentModelFailover(["a", "b", "c", "d", "e", "healthy"].map(id => entry(id)), s.circuit)(async e => { calls.push(e.model.id); return "ok"; });
|
||||||
|
assert.equal(result, "ok"); assert.deepEqual(calls, ["healthy"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("late success cannot clear a fault recorded by another in-flight request", async () => {
|
test("late success cannot clear a fault recorded by another in-flight request", async () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user