Fix test failure and address Greptile review comments
- Fix "keeps alive" test: set lastOutputAt to current time so idle reaper doesn't kill the test run (seed used a stale date) - Wire up lastOutputAt and startedAt params in test seed fixture - Remove dead wasIdle variable in clearDetachedRunWarning - Fix deferred lastOutputAt flush to use actual last output timestamp instead of wall-clock time at flush Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
942d023148
commit
aa88db7238
2 changed files with 11 additions and 7 deletions
|
|
@ -129,7 +129,8 @@ describeEmbeddedPostgres("heartbeat orphaned process recovery", () => {
|
|||
processLossRetryCount: input?.processLossRetryCount ?? 0,
|
||||
errorCode: input?.runErrorCode ?? null,
|
||||
error: input?.runError ?? null,
|
||||
startedAt: now,
|
||||
startedAt: input?.startedAt ?? now,
|
||||
lastOutputAt: input?.lastOutputAt ?? null,
|
||||
updatedAt: new Date("2026-03-19T00:00:00.000Z"),
|
||||
});
|
||||
|
||||
|
|
@ -159,6 +160,7 @@ describeEmbeddedPostgres("heartbeat orphaned process recovery", () => {
|
|||
const { runId, wakeupRequestId } = await seedRunFixture({
|
||||
processPid: child.pid ?? null,
|
||||
includeIssue: false,
|
||||
lastOutputAt: new Date(),
|
||||
});
|
||||
const heartbeat = heartbeatService(db);
|
||||
|
||||
|
|
|
|||
|
|
@ -1506,7 +1506,6 @@ export function heartbeatService(db: Db) {
|
|||
.then((rows) => rows[0] ?? null);
|
||||
if (!updated) return null;
|
||||
|
||||
const wasIdle = updated.errorCode === null; // errorCode was cleared
|
||||
await appendRunEvent(updated, await nextRunEventSeq(updated.id), {
|
||||
eventType: "lifecycle",
|
||||
stream: "system",
|
||||
|
|
@ -2509,27 +2508,30 @@ export function heartbeatService(db: Db) {
|
|||
|
||||
const currentUserRedactionOptions = await getCurrentUserRedactionOptions();
|
||||
let lastOutputAtFlushPending = false;
|
||||
let lastOutputAtLatest: Date | null = null;
|
||||
const onLog = async (stream: "stdout" | "stderr", chunk: string) => {
|
||||
const sanitizedChunk = redactCurrentUserText(chunk, currentUserRedactionOptions);
|
||||
if (stream === "stdout") stdoutExcerpt = appendExcerpt(stdoutExcerpt, sanitizedChunk);
|
||||
if (stream === "stderr") stderrExcerpt = appendExcerpt(stderrExcerpt, sanitizedChunk);
|
||||
const ts = new Date().toISOString();
|
||||
lastOutputAtLatest = new Date(ts);
|
||||
|
||||
// Batch lastOutputAt writes — flush at most once per 30 seconds to avoid DB churn
|
||||
if (!lastOutputAtFlushPending) {
|
||||
lastOutputAtFlushPending = true;
|
||||
// Flush immediately on first output
|
||||
await db.update(heartbeatRuns)
|
||||
.set({ lastOutputAt: lastOutputAtLatest, updatedAt: new Date() })
|
||||
.where(eq(heartbeatRuns.id, runId));
|
||||
setTimeout(() => {
|
||||
lastOutputAtFlushPending = false;
|
||||
if (!lastOutputAtLatest) return;
|
||||
db.update(heartbeatRuns)
|
||||
.set({ lastOutputAt: new Date(), updatedAt: new Date() })
|
||||
.set({ lastOutputAt: lastOutputAtLatest, updatedAt: new Date() })
|
||||
.where(eq(heartbeatRuns.id, runId))
|
||||
.then(() => {})
|
||||
.catch((err) => logger.warn({ err, runId }, "failed to flush lastOutputAt"));
|
||||
}, 30_000);
|
||||
// Also flush immediately on first output
|
||||
await db.update(heartbeatRuns)
|
||||
.set({ lastOutputAt: new Date(ts), updatedAt: new Date() })
|
||||
.where(eq(heartbeatRuns.id, runId));
|
||||
}
|
||||
|
||||
if (handle) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue