fix(pr-daemon): defer session creation when maestro is unreachable
When maestro goes down, the daemon only sees aoe sessions. If a PR's session lives in maestro, route() finds no match and creates a duplicate on aoe. Track maestro health with exponential backoff and suppress session creation until it answers again. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
6b3cabe76a
commit
7d95f5ceff
@@ -482,14 +482,26 @@ const MAESTRO_STATE: Record<string, string> = {
|
||||
// working -- so it degrades to an empty list. Logged once per outage, because
|
||||
// silently routing to half the sessions is exactly the failure this fixes.
|
||||
let maestroWarned = false;
|
||||
let maestroHealthy = true;
|
||||
let maestroBackoff = 10_000;
|
||||
let maestroNextRetry = 0;
|
||||
const MAESTRO_BACKOFF_MAX = 300_000;
|
||||
|
||||
async function maestroRows(): Promise<any[]> {
|
||||
if (Date.now() < maestroNextRetry) return [];
|
||||
try {
|
||||
const rows = JSON.parse(await maestro(["list", "--json"])).sessions ?? [];
|
||||
maestroWarned = false;
|
||||
maestroHealthy = true;
|
||||
maestroBackoff = 10_000;
|
||||
maestroNextRetry = 0;
|
||||
return rows;
|
||||
} catch (e) {
|
||||
if (!maestroWarned) log(`maestro list failed, its sessions are invisible until it answers: ${e}`);
|
||||
maestroWarned = true;
|
||||
maestroHealthy = false;
|
||||
maestroNextRetry = Date.now() + maestroBackoff;
|
||||
maestroBackoff = Math.min(maestroBackoff * 2, MAESTRO_BACKOFF_MAX);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -927,6 +939,12 @@ async function evaluate(prs: Pr[], mentioned: Set<string>, budget: { sessions: n
|
||||
const skill = role === "land" ? "land" : "review-pr";
|
||||
|
||||
if (!session) {
|
||||
// Maestro is unreachable: the session we cannot see may be the one
|
||||
// that owns this branch. Defer creation until maestro answers again.
|
||||
if (!maestroHealthy) {
|
||||
log(`maestro unreachable, deferring ${full.key} (${role}) to avoid duplicates`);
|
||||
continue;
|
||||
}
|
||||
// Epoch gates session creation, not hint delivery: an old PR you want
|
||||
// covered gets covered by starting a session on its branch by hand.
|
||||
if (preEpoch && !mentioned.has(full.key)) continue;
|
||||
|
||||
Reference in New Issue
Block a user