Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 43 additions & 16 deletions apps/cli/src/api/session/sessionWritesBestEffort.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
import type { AgentState, Metadata } from '@/api/types';
import { logger } from '@/ui/logger';

const BEST_EFFORT_MAX_ATTEMPTS = 3;
const BEST_EFFORT_RETRY_DELAYS_MS = [1_000, 2_000];
Comment thread
eusip marked this conversation as resolved.
Outdated

async function withRetry(
fn: () => Promise<void> | void,
onFailure: (error: unknown, attempt: number, isFinal: boolean) => void,
): Promise<void> {
for (let attempt = 1; attempt <= BEST_EFFORT_MAX_ATTEMPTS; attempt++) {
try {
await Promise.resolve(fn());
return;
} catch (error) {
const isFinal = attempt >= BEST_EFFORT_MAX_ATTEMPTS;
onFailure(error, attempt, isFinal);
if (!isFinal) {
await new Promise<void>((resolve) =>
setTimeout(resolve, BEST_EFFORT_RETRY_DELAYS_MS[attempt - 1]),
);
}
Comment thread
eusip marked this conversation as resolved.
}
}
}
Comment thread
eusip marked this conversation as resolved.

export function updateAgentStateBestEffort(
session: Readonly<{ updateAgentState: (updater: (state: AgentState) => AgentState) => Promise<void> | void }>,
updater: (state: AgentState) => AgentState,
logPrefix: string,
reason: string,
): void {
try {
const result = session.updateAgentState(updater);
void Promise.resolve(result).catch((error) => {
logger.debug(`${logPrefix} Failed to update agent state (${reason}) (non-fatal)`, error);
});
} catch (error) {
logger.debug(`${logPrefix} Failed to update agent state (${reason}) (non-fatal)`, error);
}
void withRetry(
() => session.updateAgentState(updater),
(error, attempt, isFinal) => {
if (isFinal) {
logger.debug(`${logPrefix} Failed to update agent state (${reason}) after ${BEST_EFFORT_MAX_ATTEMPTS} attempts (non-fatal)`, error);
} else {
logger.debug(`${logPrefix} Failed to update agent state (${reason}), retrying (attempt ${attempt}/${BEST_EFFORT_MAX_ATTEMPTS}) (non-fatal)`, error);
}
},
);
}

export function updateMetadataBestEffort(
Expand All @@ -23,12 +48,14 @@ export function updateMetadataBestEffort(
logPrefix: string,
reason: string,
): void {
try {
const result = session.updateMetadata(updater);
void Promise.resolve(result).catch((error) => {
logger.debug(`${logPrefix} Failed to update session metadata (${reason}) (non-fatal)`, error);
});
} catch (error) {
logger.debug(`${logPrefix} Failed to update session metadata (${reason}) (non-fatal)`, error);
}
void withRetry(
() => session.updateMetadata(updater),
(error, attempt, isFinal) => {
if (isFinal) {
logger.debug(`${logPrefix} Failed to update session metadata (${reason}) after ${BEST_EFFORT_MAX_ATTEMPTS} attempts (non-fatal)`, error);
} else {
logger.debug(`${logPrefix} Failed to update session metadata (${reason}), retrying (attempt ${attempt}/${BEST_EFFORT_MAX_ATTEMPTS}) (non-fatal)`, error);
}
},
);
}