fix: call onSpawn after pod enters Running state to prevent UI desync

The k8s adapter never called ctx.onSpawn(), so the Paperclip server
had no processStartedAt timestamp for the run. The stale-run reaper
(reapOrphanedRuns) would then mark live k8s runs as failed/orphaned,
causing the UI to show no active runs and triggering duplicate run
attempts that hit the concurrency guard.

Uses pid=-1 as a sentinel since there is no local process — the
server's isProcessAlive check safely returns false for pid <= 0.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Test User
2026-04-16 15:40:13 +00:00
parent ddb1ea4311
commit da709770f0
+13
View File
@@ -387,6 +387,19 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
try {
podName = await waitForPod(namespace, jobName, scheduleTimeoutMs, onLog, kubeconfigPath);
await onLog("stdout", `[paperclip] Pod running: ${podName}\n`);
// Notify the server that execution has started. Without this call,
// the server has no processStartedAt timestamp for the run, so the
// stale-run reaper (reapOrphanedRuns) cannot distinguish a live K8s
// job from an orphaned run and may mark it as failed — causing the
// UI to show no active runs and triggering duplicate run attempts.
if (ctx.onSpawn) {
await ctx.onSpawn({
pid: -1, // no local process; sentinel for K8s Job
processGroupId: null,
startedAt: new Date().toISOString(),
});
}
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
await onLog("stderr", `[paperclip] Pod scheduling failed: ${msg}\n`);