perf: speed exec event test waits

This commit is contained in:
Peter Steinberger
2026-04-18 16:22:11 +01:00
parent c035c5c0d2
commit 4852935e8e
3 changed files with 44 additions and 6 deletions

View File

@@ -302,7 +302,9 @@ function maybeNotifyOnExit(session: ProcessSession, status: "completed" | "faile
deliveryContext: session.notifyDeliveryContext,
trusted: false,
});
requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));
requestHeartbeatNow(
scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event", coalesceMs: 0 }),
);
}
export function createApprovalSlug(id: string) {
@@ -378,7 +380,9 @@ export function emitExecSystemEvent(
contextKey: opts.contextKey,
deliveryContext: opts.deliveryContext,
});
requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));
requestHeartbeatNow(
scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event", coalesceMs: 0 }),
);
}
function joinExecFailureOutput(aggregated: string, reason: string) {

View File

@@ -13,7 +13,15 @@ import {
resetSystemEventsForTest,
} from "../infra/system-events.js";
import { captureEnv } from "../test-utils/env.js";
import { getFinishedSession, resetProcessRegistryForTests } from "./bash-process-registry.js";
import {
addSession,
appendOutput,
getFinishedSession,
markBackgrounded,
markExited,
resetProcessRegistryForTests,
type ProcessSession,
} from "./bash-process-registry.js";
import { createExecTool, createProcessTool } from "./bash-tools.js";
import { resolveShellFromPath, sanitizeBinaryOutput } from "./shell-utils.js";
@@ -99,7 +107,6 @@ const withLabel = <T extends object>(label: string, fields: T): T & LabeledCase
// Both PowerShell and bash use ; for command separation
const joinCommands = (commands: string[]) => commands.join("; ");
const echoAfterDelay = (message: string) => joinCommands([shortDelayCmd, shellEcho(message)]);
const echoLines = (lines: string[]) => joinCommands(lines.map((line) => shellEcho(line)));
const normalizeText = (value?: string) =>
sanitizeBinaryOutput(value ?? "")
.replace(/\r\n/g, "\n")
@@ -401,7 +408,7 @@ const readBackgroundLogSnapshot = async (
lines: string[],
options: ProcessLogWindow = {},
): Promise<ProcessLogSnapshot> => {
const { sessionId } = await runBackgroundCommandToCompletion(execTool, echoLines(lines));
const sessionId = seedFinishedLogSession(lines);
const log = await readProcessLog(sessionId, options);
return {
text: readTextContent(log.content) ?? "",
@@ -410,6 +417,31 @@ const readBackgroundLogSnapshot = async (
totalLines: readTotalLines(log.details),
};
};
const seedFinishedLogSession = (lines: string[]) => {
const session: ProcessSession = {
id: `seeded-log-${nextCallId()}`,
command: "seeded log",
startedAt: Date.now(),
maxOutputChars: 100_000,
pendingMaxOutputChars: 100_000,
pendingStdout: [],
pendingStderr: [],
pendingStdoutChars: 0,
pendingStderrChars: 0,
totalOutputChars: 0,
aggregated: "",
tail: "",
exited: false,
truncated: false,
backgrounded: false,
cursorKeyMode: "unknown",
};
addSession(session);
appendOutput(session, "stdout", lines.join("\n"));
markBackgrounded(session);
markExited(session, 0, null, PROCESS_STATUS_COMPLETED);
return session.id;
};
const runLongLogExpectationCase = async ({
options,
firstLine,

View File

@@ -693,7 +693,9 @@ export const handleNodeEvent = async (ctx: NodeEventContext, nodeId: string, evt
// Scope wakes only for canonical agent sessions. Synthetic node-* fallback
// keys should keep legacy unscoped behavior so enabled non-main heartbeat
// agents still run when no explicit agent session is provided.
requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));
requestHeartbeatNow(
scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event", coalesceMs: 0 }),
);
}
return;
}