feat: global failover + dashboard model config section
- Failover is now global (account-level, not per-channel) - Dashboard shows role model config (Owner/Reviewer/Arbiter + MoA refs) - Dashboard shows failover status when active - Auto-clear failover on successful Claude rotation - Remove per-channel lease writes from failover path
This commit is contained in:
55
src/index.ts
55
src/index.ts
@@ -83,8 +83,8 @@ import {
|
||||
stopTokenRefreshLoop,
|
||||
} from './token-refresh.js';
|
||||
import {
|
||||
getActiveCodexFailoverLeases,
|
||||
restoreDefaultChannelLease,
|
||||
clearGlobalFailover,
|
||||
getGlobalFailoverInfo,
|
||||
} from './service-routing.js';
|
||||
import { FAILOVER_MIN_DURATION_MS } from './config.js';
|
||||
import { startCredentialProxy } from './credential-proxy.js';
|
||||
@@ -536,43 +536,20 @@ async function main(): Promise<void> {
|
||||
});
|
||||
|
||||
leaseRecoveryTimer = setInterval(() => {
|
||||
if (!hasAvailableClaudeToken()) {
|
||||
return;
|
||||
}
|
||||
const now = Date.now();
|
||||
for (const lease of getActiveCodexFailoverLeases()) {
|
||||
const activatedMs = lease.activatedAt
|
||||
? new Date(lease.activatedAt).getTime()
|
||||
: NaN;
|
||||
if (Number.isNaN(activatedMs)) {
|
||||
logger.warn(
|
||||
{ chatJid: lease.chatJid, activatedAt: lease.activatedAt },
|
||||
'Failover lease has unparseable activated_at, skipping auto-restore',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const elapsed = now - activatedMs;
|
||||
if (elapsed < FAILOVER_MIN_DURATION_MS) {
|
||||
logger.debug(
|
||||
{
|
||||
chatJid: lease.chatJid,
|
||||
elapsedMin: Math.round(elapsed / 60_000),
|
||||
minDurationMin: Math.round(FAILOVER_MIN_DURATION_MS / 60_000),
|
||||
},
|
||||
'Failover lease still within minimum hold period, skipping restore',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
restoreDefaultChannelLease(lease.chatJid);
|
||||
logger.info(
|
||||
{
|
||||
chatJid: lease.chatJid,
|
||||
serviceId: SERVICE_ID,
|
||||
elapsedMin: Math.round(elapsed / 60_000),
|
||||
},
|
||||
'Claude token available and failover hold period elapsed, restored default channel lease',
|
||||
);
|
||||
}
|
||||
const failover = getGlobalFailoverInfo();
|
||||
if (!failover.active) return;
|
||||
if (!hasAvailableClaudeToken()) return;
|
||||
const activatedMs = failover.activatedAt
|
||||
? new Date(failover.activatedAt).getTime()
|
||||
: NaN;
|
||||
if (Number.isNaN(activatedMs)) return;
|
||||
const elapsed = Date.now() - activatedMs;
|
||||
if (elapsed < FAILOVER_MIN_DURATION_MS) return;
|
||||
clearGlobalFailover();
|
||||
logger.info(
|
||||
{ elapsedMin: Math.round(elapsed / 60_000) },
|
||||
'Claude token available and hold period elapsed, global failover cleared',
|
||||
);
|
||||
}, 5_000);
|
||||
runtime.startMessageLoop().catch((err) => {
|
||||
logger.fatal({ err }, 'Message loop crashed unexpectedly');
|
||||
|
||||
Reference in New Issue
Block a user