mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 10:08:13 +00:00
* perf(watcher): flush file changes on a steady cadence instead of waiting for quiet Watcher batches used a 150 ms trailing debounce capped at 500 ms, so a worktree with agents writing continuously always waited the full cap. The git status nudge had no cap and could starve until the 60 s safety poll. Batches now flush 25 ms after the first change following a quiet period, then at most every 100 ms; new events join an armed flush instead of pushing it back. * fix(watcher): keep atomic saves in one batch and survive clock jumps Raise the first-flush delay to 75 ms so the native watcher's split burst lands in one batch, cap the flush delay at one interval so a backwards clock jump can't stall delivery, and widen the editor delete debounce to cover a split across one flush interval. * test: wait past the widened editor delete debounce * fix(watcher): keep markdown list refreshing under sustained writes and widen delete grace Markdown document refresh used a resetting 125 ms debounce that never fired once watch batches arrive every 100 ms. Delete tombstones now wait two batch intervals so slow stat calls (WSL, AV scans) can't split a save into a flash. * fix(watcher): bound watcher-driven reads and scans under sustained writes One watcher-triggered editor read and one markdown scan per target in flight, with a single follow-up; markdown scans honour the latest change time; the headless Windows watcher no longer resets its refresh timer on every event. * fix(watcher): make the faster remote cadence opt-in and harden watcher-driven reloads files.watch takes an optional batchCadence; hosts keep legacy trailing batching unless the client opts in. Coalesced editor follow-ups re-check the tab and replace a hung read only once; Markdown mounts skip pre-change scans; the Windows fallback refreshes the whole tree at most every 500 ms. * fix(watcher): stop restarting the remaining watch-driven timers Combined-diff section reloads and per-file editor reload dispatch no longer push an armed timer back; a queued editor follow-up for a tab that left the screen marks it stale instead of dropping the change. * fix(watcher): let combined-diff and worktree notifications land under sustained writes A combined-diff section discards an invalidated in-flight load at most once in a row; worktree base-directory notifications no longer restart their timer. * fix(watcher): never overwrite an edited diff section and unstick hung reloads A combined-diff load never commits over a section with unsaved edits; a reload queued behind a hung read starts after the stale limit without needing another change event. * fix(watcher): recover from hung markdown scans and keep evidence for edited tabs A Markdown scan that never settles is abandoned after the join window so later changes scan again; a queued editor follow-up for a tab edited meanwhile marks it changed-on-disk and stale instead of dropping the change. * chore(watcher): use a numeric markdown scan id * fix(watcher): don't let later events join a stale echo-verification read Payloads from the same burst still share the in-flight read; a payload from a later task gets exactly one fresh read issued after the current one settles.
23 lines
1.1 KiB
TypeScript
23 lines
1.1 KiB
TypeScript
// Why: the main-process watcher batcher and the runtime files.watch batcher
|
|
// share one flush window so local and remote latency can't drift.
|
|
|
|
// Why: a trailing debounce never fires while agents write continuously, so a
|
|
// busy worktree waited for the max-wait cap on every batch. Instead the first
|
|
// change after a quiet period flushes after a short coalescing tick, and a
|
|
// sustained stream flushes on a fixed cadence.
|
|
// Why 75: the native watcher sends a burst's first event alone and the rest
|
|
// ~50ms later; a shorter window splits atomic saves (tmp create + rename).
|
|
export const WATCH_BATCH_LEADING_MS = 75
|
|
export const WATCH_BATCH_INTERVAL_MS = 100
|
|
|
|
/** Delay before flushing a batch armed at `now`; `lastFlushAt` is 0 before the first flush. */
|
|
export function watchBatchFlushDelayMs(
|
|
now: number,
|
|
lastFlushAt: number,
|
|
leadingMs: number = WATCH_BATCH_LEADING_MS,
|
|
intervalMs: number = WATCH_BATCH_INTERVAL_MS
|
|
): number {
|
|
// Why cap at intervalMs: a backwards wall-clock jump must not stall delivery.
|
|
return Math.min(intervalMs, Math.max(leadingMs, lastFlushAt + intervalMs - now))
|
|
}
|