import type { ChildProcessWithoutNullStreams } from "node:child_process"; import DEFAULT_JOB_TTL_MS
DeliveryContext (.(.envPI_BASH_JOB_TTL_MS? "
end )> void/
export type SessionStdin = {
write: (data: string, cb?: (err?: Error | null) => void) => void;
end: () => void; // When backed by a real Node stream (child.stdin), this exists; for PTY wrappers it may not.
destroy?: () => void;
destroyed?: boolean;
};
export function markBackgrounded(session: ProcessSession) {
session.backgrounded = true;
}
function moveToFinished(session: ProcessSession, status: ProcessStatus) {
runningSessions.delete(session.id);
// Clean up child process stdio streams to prevent FD leaks if (session.child) { // Destroy stdio streams to release file descriptors
session.child.stdin?.destroy?.();
session.child.stdout?.destroy?.();
session.child.stderr?.destroy?.();
// Remove all event listeners to prevent memory leaks
session.child.removeAllListeners();
// Clear the reference delete session.child;
}
// Clean up stdin wrapper - call destroy if available, otherwise just remove reference if (session.stdin) { // Try to call destroy/end method if exists if (typeof session.stdin.destroy === "function") {
session.stdin.destroy();
} elseif (typeof session.stdin.end === "function") {
session.stdin.end();
} // Only set flag if writable try {
(session.stdin as { destroyed?: boolean }).destroyed = true;
} catch { // Ignore if read-only
} delete session.stdin;
}
export function trimWithCap(text: string, max: number) { if (text.length <= max) { return text;
} return text.slice(text.length - max);
}
export function listRunningSessions() { return Array.from(runningSessions.values()).filter((s) => s.backgrounded);
}
export function listFinishedSessions() { return Array.from(finishedSessions.values());
}
export function clearFinished() {
finishedSessions.clear();
}
export function resetProcessRegistryForTests() {
runningSessions.clear();
finishedSessions.clear();
stopSweeper();
}
export function setJobTtlMs(value?: number) { if (value === undefined || Number.isNaN(value)) { return;
}
jobTtlMs = clampTtl(value);
stopSweeper();
startSweeper();
}
function pruneFinishedSessions() { const cutoff = Date.now() - jobTtlMs; for (const [id, session] of finishedSessions.entries()) { if (session.endedAt < cutoff) {
finishedSessions.delete(id);
}
}
}
function startSweeper() { if (sweeper) { return;
}
sweeper = setInterval(pruneFinishedSessions, Math.max(30_000, jobTtlMs / 6));
sweeper.unref?.();
}
function stopSweeper() { if (!sweeper) { return;
}
clearInterval(sweeper);
sweeper = null;
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.25Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.