Stabilize paired-room orchestration and Codex app-server flow

This commit is contained in:
Eyejoker
2026-03-19 02:57:14 +09:00
parent b710d4a33d
commit 779d57c392
32 changed files with 2517 additions and 185 deletions

View File

@@ -32,6 +32,8 @@ interface GroupState {
processName: string | null;
groupFolder: string | null;
retryCount: number;
retryTimer: ReturnType<typeof setTimeout> | null;
retryScheduledAt: number | null;
startedAt: number | null;
}
@@ -68,6 +70,8 @@ export class GroupQueue {
processName: null,
groupFolder: null,
retryCount: 0,
retryTimer: null,
retryScheduledAt: null,
startedAt: null,
};
this.groups.set(groupJid, state);
@@ -101,6 +105,22 @@ export class GroupQueue {
return;
}
if (
state.retryScheduledAt !== null &&
Date.now() < state.retryScheduledAt
) {
state.pendingMessages = true;
logger.debug(
{
groupJid,
retryCount: state.retryCount,
retryScheduledAt: state.retryScheduledAt,
},
'Retry backoff active, message queued until retry window opens',
);
return;
}
if (this.activeCount >= MAX_CONCURRENT_AGENTS) {
state.pendingMessages = true;
if (!this.waitingGroups.includes(groupJid)) {
@@ -335,6 +355,7 @@ export class GroupQueue {
});
if (success) {
state.retryCount = 0;
state.retryScheduledAt = null;
} else {
outcome = 'retry_scheduled';
this.scheduleRetry(groupJid, state, runId);
@@ -415,6 +436,11 @@ export class GroupQueue {
): void {
state.retryCount++;
if (state.retryCount > MAX_RETRIES) {
if (state.retryTimer) {
clearTimeout(state.retryTimer);
state.retryTimer = null;
}
state.retryScheduledAt = null;
logger.error(
{ groupJid, runId, retryCount: state.retryCount },
'Max retries exceeded, dropping messages (will retry on next incoming message)',
@@ -424,11 +450,17 @@ export class GroupQueue {
}
const delayMs = BASE_RETRY_MS * Math.pow(2, state.retryCount - 1);
state.retryScheduledAt = Date.now() + delayMs;
logger.info(
{ groupJid, runId, retryCount: state.retryCount, delayMs },
'Scheduling retry with backoff',
);
setTimeout(() => {
if (state.retryTimer) {
clearTimeout(state.retryTimer);
}
state.retryTimer = setTimeout(() => {
state.retryTimer = null;
state.retryScheduledAt = null;
if (!this.shuttingDown) {
this.enqueueMessageCheck(groupJid);
}