mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 15:01:23 +00:00
refactor: harden log stream writes
This commit is contained in:
64
src/terminal/stream-writer.ts
Normal file
64
src/terminal/stream-writer.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
export type SafeStreamWriterOptions = {
|
||||
beforeWrite?: () => void;
|
||||
onBrokenPipe?: (err: NodeJS.ErrnoException, stream: NodeJS.WriteStream) => void;
|
||||
};
|
||||
|
||||
export type SafeStreamWriter = {
|
||||
write: (stream: NodeJS.WriteStream, text: string) => boolean;
|
||||
writeLine: (stream: NodeJS.WriteStream, text: string) => boolean;
|
||||
reset: () => void;
|
||||
isClosed: () => boolean;
|
||||
};
|
||||
|
||||
function isBrokenPipeError(err: unknown): err is NodeJS.ErrnoException {
|
||||
const code = (err as NodeJS.ErrnoException)?.code;
|
||||
return code === "EPIPE" || code === "EIO";
|
||||
}
|
||||
|
||||
export function createSafeStreamWriter(options: SafeStreamWriterOptions = {}): SafeStreamWriter {
|
||||
let closed = false;
|
||||
let notified = false;
|
||||
|
||||
const noteBrokenPipe = (err: NodeJS.ErrnoException, stream: NodeJS.WriteStream) => {
|
||||
if (notified) return;
|
||||
notified = true;
|
||||
options.onBrokenPipe?.(err, stream);
|
||||
};
|
||||
|
||||
const handleError = (err: unknown, stream: NodeJS.WriteStream): boolean => {
|
||||
if (!isBrokenPipeError(err)) {
|
||||
throw err;
|
||||
}
|
||||
closed = true;
|
||||
noteBrokenPipe(err, stream);
|
||||
return false;
|
||||
};
|
||||
|
||||
const write = (stream: NodeJS.WriteStream, text: string): boolean => {
|
||||
if (closed) return false;
|
||||
try {
|
||||
options.beforeWrite?.();
|
||||
} catch (err) {
|
||||
return handleError(err, process.stderr);
|
||||
}
|
||||
try {
|
||||
stream.write(text);
|
||||
return !closed;
|
||||
} catch (err) {
|
||||
return handleError(err, stream);
|
||||
}
|
||||
};
|
||||
|
||||
const writeLine = (stream: NodeJS.WriteStream, text: string): boolean =>
|
||||
write(stream, `${text}\n`);
|
||||
|
||||
return {
|
||||
write,
|
||||
writeLine,
|
||||
reset: () => {
|
||||
closed = false;
|
||||
notified = false;
|
||||
},
|
||||
isClosed: () => closed,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user