History

Use React Pacer throttler for domain event snapshot sync

- Replace manual timeout-based domain event batching with `Throttler` - Keep provider query invalidation batched with trailing 100ms flushes - Cancel throttler and reset invalidation flag during EventRouter cleanup

Julius Marminge committed 8 months ago

Commit e7650511 parent f5e4df51 file · +19 −24Browse files

Unified · Split

apps/web/src/routes/__root.tsx+19−24
@@ -8,6 +8,7 @@ import { · 7 unmodified lines
8} from "@tanstack/react-router";8} from "@tanstack/react-router";
9import { useEffect, useRef } from "react";9import { useEffect, useRef } from "react";
10import { QueryClient, useQueryClient } from "@tanstack/react-query";10import { QueryClient, useQueryClient } from "@tanstack/react-query";
11import { Throttler } from "@tanstack/react-pacer";
11 12
12import { APP_DISPLAY_NAME } from "../branding";13import { APP_DISPLAY_NAME } from "../branding";
13import { Button } from "../components/ui/button";14import { Button } from "../components/ui/button";
@@ -150,6 +151,7 @@ function EventRouter() { · 136 unmodified lines
150 let latestSequence = 0;151 let latestSequence = 0;
151 let syncing = false;152 let syncing = false;
152 let pending = false;153 let pending = false;
154 let needsProviderInvalidation = false;
153 155
154 const flushSnapshotSync = async (): Promise<void> => {156 const flushSnapshotSync = async (): Promise<void> => {
155 const snapshot = await api.orchestration.getSnapshot();157 const snapshot = await api.orchestration.getSnapshot();
@@ -185,21 +187,20 @@ function EventRouter() { · 29 unmodified lines
185 syncing = false;187 syncing = false;
186 };188 };
187 189
188 void syncSnapshot().catch(() => undefined);190 const domainEventFlushThrottler = new Throttler(
189 191 () => {
190 // Batch domain events: collect over a short window then sync once.192 if (needsProviderInvalidation) {
191 const DOMAIN_EVENT_BATCH_MS = 100;193 needsProviderInvalidation = false;
192 let batchTimer: ReturnType<typeof setTimeout> | null = null;194 void queryClient.invalidateQueries({ queryKey: providerQueryKeys.all });
193 let needsProviderInvalidation = false;195 }
194 196 void syncSnapshot();
195 const flushBatch = () => {197 },
196 batchTimer = null;198 {
197 if (needsProviderInvalidation) {199 wait: 100,
198 needsProviderInvalidation = false;200 leading: false,
199 void queryClient.invalidateQueries({ queryKey: providerQueryKeys.all });201 trailing: true,
200 }202 },
201 void syncSnapshot();203 );
202 };
203 204
204 const unsubDomainEvent = api.orchestration.onDomainEvent((event) => {205 const unsubDomainEvent = api.orchestration.onDomainEvent((event) => {
205 if (event.sequence <= latestSequence) {206 if (event.sequence <= latestSequence) {
@@ -209,12 +210,7 @@ function EventRouter() { · 3 unmodified lines
209 if (event.type === "thread.turn-diff-completed" || event.type === "thread.reverted") {210 if (event.type === "thread.turn-diff-completed" || event.type === "thread.reverted") {
210 needsProviderInvalidation = true;211 needsProviderInvalidation = true;
211 }212 }
212 // Throttle (not debounce): schedule a flush if none is pending.213 domainEventFlushThrottler.maybeExecute();
213 // This guarantees at most one syncSnapshot per batch window
214 // without starving the UI during sustained event bursts.
215 if (batchTimer === null) {
216 batchTimer = setTimeout(flushBatch, DOMAIN_EVENT_BATCH_MS);
217 }
218 });214 });
219 const unsubTerminalEvent = api.terminal.onEvent((event) => {215 const unsubTerminalEvent = api.terminal.onEvent((event) => {
220 const hasRunningSubprocess = terminalRunningSubprocessFromEvent(event);216 const hasRunningSubprocess = terminalRunningSubprocessFromEvent(event);
@@ -299,9 +295,8 @@ function EventRouter() { · 78 unmodified lines
299 });295 });
300 return () => {296 return () => {
301 disposed = true;297 disposed = true;
302 if (batchTimer !== null) {298 needsProviderInvalidation = false;
303 clearTimeout(batchTimer);299 domainEventFlushThrottler.cancel();
304 }
305 unsubDomainEvent();300 unsubDomainEvent();
306 unsubTerminalEvent();301 unsubTerminalEvent();
307 unsubWelcome();302 unsubWelcome();

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t