init claude-code
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
type WriteFn = (content: string) => void
|
||||
|
||||
export type BufferedWriter = {
|
||||
write: (content: string) => void
|
||||
flush: () => void
|
||||
dispose: () => void
|
||||
}
|
||||
|
||||
export function createBufferedWriter({
|
||||
writeFn,
|
||||
flushIntervalMs = 1000,
|
||||
maxBufferSize = 100,
|
||||
maxBufferBytes = Infinity,
|
||||
immediateMode = false,
|
||||
}: {
|
||||
writeFn: WriteFn
|
||||
flushIntervalMs?: number
|
||||
maxBufferSize?: number
|
||||
maxBufferBytes?: number
|
||||
immediateMode?: boolean
|
||||
}): BufferedWriter {
|
||||
let buffer: string[] = []
|
||||
let bufferBytes = 0
|
||||
let flushTimer: NodeJS.Timeout | null = null
|
||||
// Batch detached by overflow that hasn't been written yet. Tracked so
|
||||
// flush()/dispose() can drain it synchronously if the process exits
|
||||
// before the setImmediate fires.
|
||||
let pendingOverflow: string[] | null = null
|
||||
|
||||
function clearTimer(): void {
|
||||
if (flushTimer) {
|
||||
clearTimeout(flushTimer)
|
||||
flushTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
function flush(): void {
|
||||
if (pendingOverflow) {
|
||||
writeFn(pendingOverflow.join(''))
|
||||
pendingOverflow = null
|
||||
}
|
||||
if (buffer.length === 0) return
|
||||
writeFn(buffer.join(''))
|
||||
buffer = []
|
||||
bufferBytes = 0
|
||||
clearTimer()
|
||||
}
|
||||
|
||||
function scheduleFlush(): void {
|
||||
if (!flushTimer) {
|
||||
flushTimer = setTimeout(flush, flushIntervalMs)
|
||||
}
|
||||
}
|
||||
|
||||
// Detach the buffer synchronously so the caller never waits on writeFn.
|
||||
// writeFn may block (e.g. errorLogSink.ts appendFileSync) — if overflow fires
|
||||
// mid-render or mid-keystroke, deferring the write keeps the current tick
|
||||
// short. Timer-based flushes already run outside user code paths so they
|
||||
// stay synchronous.
|
||||
function flushDeferred(): void {
|
||||
if (pendingOverflow) {
|
||||
// A previous overflow write is still queued. Coalesce into it to
|
||||
// preserve ordering — writes land in a single setImmediate-ordered batch.
|
||||
pendingOverflow.push(...buffer)
|
||||
buffer = []
|
||||
bufferBytes = 0
|
||||
clearTimer()
|
||||
return
|
||||
}
|
||||
const detached = buffer
|
||||
buffer = []
|
||||
bufferBytes = 0
|
||||
clearTimer()
|
||||
pendingOverflow = detached
|
||||
setImmediate(() => {
|
||||
const toWrite = pendingOverflow
|
||||
pendingOverflow = null
|
||||
if (toWrite) writeFn(toWrite.join(''))
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
write(content: string): void {
|
||||
if (immediateMode) {
|
||||
writeFn(content)
|
||||
return
|
||||
}
|
||||
buffer.push(content)
|
||||
bufferBytes += content.length
|
||||
scheduleFlush()
|
||||
if (buffer.length >= maxBufferSize || bufferBytes >= maxBufferBytes) {
|
||||
flushDeferred()
|
||||
}
|
||||
},
|
||||
flush,
|
||||
dispose(): void {
|
||||
flush()
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user