Skip to content

Commit b81d7ef

Browse files
fix: log terminal session persistence failures
1 parent be94853 commit b81d7ef

4 files changed

Lines changed: 27 additions & 2 deletions

File tree

src/gateway/server-chat.agent-events.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ describe("agent event handler", () => {
9797
const broadcast = vi.fn();
9898
const broadcastToConnIds = vi.fn();
9999
const nodeSendToSession = vi.fn();
100+
const logGateway = { error: vi.fn() };
100101
const clearAgentRunContext = vi.fn();
101102
const clearTrackedActiveRun =
102103
vi.fn<NonNullable<AgentEventHandlerOptions["clearTrackedActiveRun"]>>();
@@ -117,6 +118,7 @@ describe("agent event handler", () => {
117118
toolEventRecipients,
118119
sessionEventSubscribers,
119120
sessionMessageSubscribers,
121+
logGateway,
120122
loadGatewaySessionRowForSnapshot: loadGatewaySessionRow,
121123
lifecycleErrorRetryGraceMs: params?.lifecycleErrorRetryGraceMs,
122124
isChatSendRunActive: params?.isChatSendRunActive,
@@ -131,6 +133,7 @@ describe("agent event handler", () => {
131133
broadcast,
132134
broadcastToConnIds,
133135
nodeSendToSession,
136+
logGateway,
134137
clearAgentRunContext,
135138
clearTrackedActiveRun,
136139
agentRunSeq,
@@ -2502,7 +2505,7 @@ describe("agent event handler", () => {
25022505
});
25032506
persistGatewaySessionLifecycleEventMock.mockRejectedValueOnce(new Error("disk full"));
25042507
const markTrackedRunTerminalPersisted = vi.fn();
2505-
const { broadcastToConnIds, handler, sessionEventSubscribers } = createHarness({
2508+
const { broadcastToConnIds, handler, logGateway, sessionEventSubscribers } = createHarness({
25062509
resolveSessionKeyForRun: () => "session-failed-write",
25072510
lifecycleErrorRetryGraceMs: 0,
25082511
markTrackedRunTerminalPersisted,
@@ -2532,6 +2535,15 @@ describe("agent event handler", () => {
25322535
updatedAt: 2_100,
25332536
abortedLastRun: false,
25342537
});
2538+
expect(logGateway.error).toHaveBeenCalledWith(
2539+
"terminal session persistence failed",
2540+
expect.objectContaining({
2541+
runId: "run-failed-write",
2542+
clientRunId: "run-failed-write",
2543+
sessionKey: "session-failed-write",
2544+
error: expect.stringContaining("disk full"),
2545+
}),
2546+
);
25352547
expect(markTrackedRunTerminalPersisted).not.toHaveBeenCalled();
25362548
});
25372549

src/gateway/server-chat.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { getRuntimeConfig } from "../config/io.js";
99
import { type AgentEventPayload, getAgentRunContext } from "../infra/agent-events.js";
1010
import { detectErrorKind, type ErrorKind } from "../infra/errors.js";
1111
import { resolveHeartbeatVisibility } from "../infra/heartbeat-visibility.js";
12+
import type { SubsystemLogger } from "../logging/subsystem.js";
1213
import { isAcpSessionKey, isSubagentSessionKey } from "../sessions/session-key-utils.js";
1314
import { resolveAssistantEventPhase } from "../shared/chat-message-content.js";
1415
import { setSafeTimeout } from "../utils/timer-delay.js";
@@ -268,6 +269,7 @@ export type AgentEventHandlerOptions = {
268269
toolEventRecipients: ToolEventRecipientRegistry;
269270
sessionEventSubscribers: SessionEventSubscriberRegistry;
270271
sessionMessageSubscribers: SessionMessageSubscriberRegistry;
272+
logGateway?: Pick<SubsystemLogger, "error">;
271273
loadGatewaySessionRowForSnapshot?: typeof loadGatewaySessionRow;
272274
lifecycleErrorRetryGraceMs?: number;
273275
isChatSendRunActive?: (runId: string) => boolean;
@@ -307,6 +309,7 @@ export function createAgentEventHandler({
307309
toolEventRecipients,
308310
sessionEventSubscribers,
309311
sessionMessageSubscribers,
312+
logGateway,
310313
loadGatewaySessionRowForSnapshot = loadGatewaySessionRow,
311314
lifecycleErrorRetryGraceMs = AGENT_LIFECYCLE_ERROR_RETRY_GRACE_MS,
312315
isChatSendRunActive = () => false,
@@ -716,7 +719,13 @@ export function createAgentEventHandler({
716719
markPersisted();
717720
broadcastSessionChange();
718721
})
719-
.catch(() => {
722+
.catch((err: unknown) => {
723+
logGateway?.error("terminal session persistence failed", {
724+
runId: evt.runId,
725+
clientRunId,
726+
sessionKey,
727+
error: formatForLog(err),
728+
});
720729
// Persistence recovery remains tracked by the controller entry, but
721730
// subscribers still need a terminal projection instead of hanging.
722731
broadcastSessionChange(evt);

src/gateway/server-runtime-subscriptions.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Gateway event subscription wiring for agent, heartbeat, transcript, and lifecycle broadcasts.
22
import { clearAgentRunContext, onAgentEvent } from "../infra/agent-events.js";
33
import { onHeartbeatEvent } from "../infra/heartbeat-events.js";
4+
import type { SubsystemLogger } from "../logging/subsystem.js";
45
import { onSessionLifecycleEvent } from "../sessions/session-lifecycle-events.js";
56
import { onInternalSessionTranscriptUpdate } from "../sessions/transcript-events.js";
67
import type { ChatAbortControllerEntry, RestartRecoveryCandidate } from "./chat-abort.js";
@@ -28,6 +29,7 @@ export function startGatewayEventSubscriptions(params: {
2829
sessionMessageSubscribers: SessionMessageSubscriberRegistry;
2930
chatAbortControllers: Map<string, ChatAbortControllerEntry>;
3031
restartRecoveryCandidates: Map<string, RestartRecoveryCandidate>;
32+
logGateway?: Pick<SubsystemLogger, "error">;
3133
}) {
3234
let agentEventHandlerPromise: Promise<
3335
ReturnType<typeof import("./server-chat.js").createAgentEventHandler>
@@ -49,6 +51,7 @@ export function startGatewayEventSubscriptions(params: {
4951
toolEventRecipients: params.toolEventRecipients,
5052
sessionEventSubscribers: params.sessionEventSubscribers,
5153
sessionMessageSubscribers: params.sessionMessageSubscribers,
54+
logGateway: params.logGateway,
5255
clearTrackedActiveRun: ({ runId, clientRunId }) => {
5356
const candidateRunIds = runId === clientRunId ? [runId] : [runId, clientRunId];
5457
for (const candidateRunId of candidateRunIds) {

src/gateway/server.impl.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ export async function startGatewayServer(
11951195
sessionMessageSubscribers,
11961196
chatAbortControllers,
11971197
restartRecoveryCandidates,
1198+
logGateway: log,
11981199
}),
11991200
);
12001201
Object.assign(runtimeState, runtimeSubscriptions);

0 commit comments

Comments
 (0)