Files
orcs-code/src/utils/bufferedWriter.ts
did:key:z6MkqDnb7Siv3Cwj7pGJq4T5EsUisECqR8KpnDLwcaZq5TPr d2542c9a62 asdf
Squash the current repository state back into one baseline commit while
preserving the README reframing and repository contents.

Constraint: User explicitly requested a single squashed commit with subject "asdf"
Confidence: high
Scope-risk: broad
Reversibility: clean
Directive: This commit intentionally rewrites published history; coordinate before future force-pushes
Tested: git status clean; local history rewritten to one commit; force-pushed main to origin and instructkr
Not-tested: Fresh clone verification after push
2026-03-31 03:34:03 -07:00

101 lines
2.5 KiB
TypeScript

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()
},
}
}