e892346c6b05b7d9636a259e69f52dab82fd611a
1
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1656c3bb93 |
perf(sync): optimize multi-session event pipeline with per-directory queues and delta coalescing (#908)
* fix: hide archived section and empty folders when no sessions remain - Only push archived group in useSessionGrouping when there are archived sessions, preventing an empty archived section from rendering - Hide empty folders in archived bucket via shouldKeepFolder check in SessionGroupSection (folders with no sessions and no content in children are filtered out) - Always filter folders through shouldKeepFolder, not just during search * perf: memoize archived folder filtering * perf(sync): per-directory event queues to eliminate cross-session HoL blocking The SSE event pipeline previously used a single global queue and a single flush timer shared across all directories. Under concurrent multi-session workloads, a busy directory's delta storm would block other directories' status and state events from reaching the UI until the next flush tick, producing the "multi-session latency" symptom users report. Split the queue into one DirectoryQueue per directory, each with its own coalesce map, stale-delta set, and flush timer. Directories flush independently so a busy directory can no longer starve a quiet one. Coalesce keys are now scoped to a single directory's queue, so the directory prefix is removed from the key strings. Cross-directory behavior only; same-directory multi-session behavior is unchanged (React 18 auto-batching still collapses a single directory's flush into one render). * perf(sync): coalesce consecutive message.part.delta events per flush window Within a 16ms flush window, consecutive delta events for the same (messageID, partID, field) tuple are string-concatenated into a single accumulated delta rather than being queued individually. This directly addresses same-project multi-session workloads — most notably parent sessions with subagent tasks (child sessions share the same directory queue). Both parties stream deltas concurrently, which previously multiplied raw event count proportionally to the number of active sessions. Coalescing can reduce queue depth by 10-100x during active streaming. Safety: verified against event-reducer.ts — the delta handler is a pure string append (existingValue + props.delta) with no per-event side effects (no time.updated, no notifications, no diff calculations). The merged result is semantically identical to applying each delta separately. The staleDeltas skip mechanism is unaffected: accumulated delta payloads retain their type and identifiers, so message.part.updated supersession still works correctly. * test(sync): cover per-directory queues and delta coalescing Extend event-pipeline.test.js with behavioural coverage for both optimizations landed in 98d013a and 258acf0: P1 (per-directory queues) - Delivers events from two directories without loss - Keeps distinct sessionIDs in the same directory as independent coalesce slots (session.status is not overwritten across sessions) - Collapses repeated session.status for the same session down to latest Option C (delta coalescing) - Accumulates consecutive deltas for the same (messageID, partID, field) into a single dispatched event with concatenated content - Does not merge deltas across different fields on the same part - Does not merge deltas across different parts on the same message - Does not merge deltas across different directories (per-dir queues) - Skips accumulated deltas when message.part.updated is coalesced onto an earlier update, proving staleDeltas still works with C - Leaves non-delta coalescing (session.status replace semantics) intact All 13 tests pass under bun:test. Also adds event-pipeline.bench.js, a runnable synthetic benchmark that reports delta reduction and byte integrity across 8 workload scenarios from "single session, 500 tokens" up to "10 projects × 5 sessions × 1000 tokens". Run with: bun packages/ui/src/sync/__tests__/event-pipeline.bench.js Current numbers on this machine: 99.5% - 99.9% delta event reduction with full byte-level integrity (concatenated delta bytes always equal the input total). * fix(sync): remove staleDeltas — it silently drops delta events --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com> |