source dump of claude code
at main 100 lines 2.6 kB view raw
1type WriteFn = (content: string) => void 2 3export type BufferedWriter = { 4 write: (content: string) => void 5 flush: () => void 6 dispose: () => void 7} 8 9export function createBufferedWriter({ 10 writeFn, 11 flushIntervalMs = 1000, 12 maxBufferSize = 100, 13 maxBufferBytes = Infinity, 14 immediateMode = false, 15}: { 16 writeFn: WriteFn 17 flushIntervalMs?: number 18 maxBufferSize?: number 19 maxBufferBytes?: number 20 immediateMode?: boolean 21}): BufferedWriter { 22 let buffer: string[] = [] 23 let bufferBytes = 0 24 let flushTimer: NodeJS.Timeout | null = null 25 // Batch detached by overflow that hasn't been written yet. Tracked so 26 // flush()/dispose() can drain it synchronously if the process exits 27 // before the setImmediate fires. 28 let pendingOverflow: string[] | null = null 29 30 function clearTimer(): void { 31 if (flushTimer) { 32 clearTimeout(flushTimer) 33 flushTimer = null 34 } 35 } 36 37 function flush(): void { 38 if (pendingOverflow) { 39 writeFn(pendingOverflow.join('')) 40 pendingOverflow = null 41 } 42 if (buffer.length === 0) return 43 writeFn(buffer.join('')) 44 buffer = [] 45 bufferBytes = 0 46 clearTimer() 47 } 48 49 function scheduleFlush(): void { 50 if (!flushTimer) { 51 flushTimer = setTimeout(flush, flushIntervalMs) 52 } 53 } 54 55 // Detach the buffer synchronously so the caller never waits on writeFn. 56 // writeFn may block (e.g. errorLogSink.ts appendFileSync) — if overflow fires 57 // mid-render or mid-keystroke, deferring the write keeps the current tick 58 // short. Timer-based flushes already run outside user code paths so they 59 // stay synchronous. 60 function flushDeferred(): void { 61 if (pendingOverflow) { 62 // A previous overflow write is still queued. Coalesce into it to 63 // preserve ordering — writes land in a single setImmediate-ordered batch. 64 pendingOverflow.push(...buffer) 65 buffer = [] 66 bufferBytes = 0 67 clearTimer() 68 return 69 } 70 const detached = buffer 71 buffer = [] 72 bufferBytes = 0 73 clearTimer() 74 pendingOverflow = detached 75 setImmediate(() => { 76 const toWrite = pendingOverflow 77 pendingOverflow = null 78 if (toWrite) writeFn(toWrite.join('')) 79 }) 80 } 81 82 return { 83 write(content: string): void { 84 if (immediateMode) { 85 writeFn(content) 86 return 87 } 88 buffer.push(content) 89 bufferBytes += content.length 90 scheduleFlush() 91 if (buffer.length >= maxBufferSize || bufferBytes >= maxBufferBytes) { 92 flushDeferred() 93 } 94 }, 95 flush, 96 dispose(): void { 97 flush() 98 }, 99 } 100}