| author | |
| committer | |
| log | e0874b651d5c5fa5c578be932aada627b95c3f52 |
| tree | 794069696e25f8753ad79daf22cbf14c4275ac95 |
| parent | 12347082ef1c4bce3d4a96e4072b7ada9a5a5b29 |
| signature | Signed by PGP key B5690EEEBB952194 |
2 files changed, 18 insertions(+), 6 deletions(-)
apps/web/src/rpc/requestLatencyState.ts+9-3| ... | ... | @@ -3,8 +3,9 @@ import { Atom } from "effect/unstable/reactivity"; |
| 3 | 3 | |
| 4 | 4 | import { appAtomRegistry } from "./atomRegistry"; |
| 5 | 5 | |
| 6 | export const SLOW_RPC_ACK_THRESHOLD_MS = 2_500; | |
| 6 | export const SLOW_RPC_ACK_THRESHOLD_MS = 15_000; | |
| 7 | 7 | export const MAX_TRACKED_RPC_ACK_REQUESTS = 256; |
| 8 | let slowRpcAckThresholdMs = SLOW_RPC_ACK_THRESHOLD_MS; | |
| 8 | 9 | |
| 9 | 10 | export interface SlowRpcAckRequest { |
| 10 | 11 | readonly requestId: string; |
| ... | ... | @@ -56,12 +57,12 @@ export function trackRpcRequestSent(requestId: string, tag: string): void { |
| 56 | 57 | startedAt: new Date(startedAtMs).toISOString(), |
| 57 | 58 | startedAtMs, |
| 58 | 59 | tag, |
| 59 | thresholdMs: SLOW_RPC_ACK_THRESHOLD_MS, | |
| 60 | thresholdMs: slowRpcAckThresholdMs, | |
| 60 | 61 | }; |
| 61 | 62 | const timeoutId = setTimeout(() => { |
| 62 | 63 | pendingRpcAckRequests.delete(requestId); |
| 63 | 64 | appendSlowRpcAckRequest(request); |
| 64 | }, SLOW_RPC_ACK_THRESHOLD_MS); | |
| 65 | }, slowRpcAckThresholdMs); | |
| 65 | 66 | |
| 66 | 67 | pendingRpcAckRequests.set(requestId, { |
| 67 | 68 | request, |
| ... | ... | @@ -119,9 +120,14 @@ function evictOldestPendingRpcRequestIfNeeded(): void { |
| 119 | 120 | } |
| 120 | 121 | |
| 121 | 122 | export function resetRequestLatencyStateForTests(): void { |
| 123 | slowRpcAckThresholdMs = SLOW_RPC_ACK_THRESHOLD_MS; | |
| 122 | 124 | clearAllTrackedRpcRequests(); |
| 123 | 125 | } |
| 124 | 126 | |
| 127 | export function setSlowRpcAckThresholdMsForTests(thresholdMs: number): void { | |
| 128 | slowRpcAckThresholdMs = thresholdMs; | |
| 129 | } | |
| 130 | ||
| 125 | 131 | export function useSlowRpcAckRequests(): ReadonlyArray<SlowRpcAckRequest> { |
| 126 | 132 | return useAtomValue(slowRpcAckRequestsAtom); |
| 127 | 133 | } |
apps/web/src/wsTransport.test.ts+9-3| ... | ... | @@ -5,7 +5,11 @@ import { |
| 5 | 5 | __resetClientTracingForTests, |
| 6 | 6 | configureClientTracing, |
| 7 | 7 | } from "./observability/clientTracing"; |
| 8 | import { getSlowRpcAckRequests, resetRequestLatencyStateForTests } from "./rpc/requestLatencyState"; | |
| 8 | import { | |
| 9 | getSlowRpcAckRequests, | |
| 10 | resetRequestLatencyStateForTests, | |
| 11 | setSlowRpcAckThresholdMsForTests, | |
| 12 | } from "./rpc/requestLatencyState"; | |
| 9 | 13 | import { |
| 10 | 14 | getWsConnectionStatus, |
| 11 | 15 | getWsConnectionUiState, |
| ... | ... | @@ -292,6 +296,8 @@ describe("WsTransport", () => { |
| 292 | 296 | }); |
| 293 | 297 | |
| 294 | 298 | it("marks unary requests as slow until the first server ack arrives", async () => { |
| 299 | const slowAckThresholdMs = 25; | |
| 300 | setSlowRpcAckThresholdMsForTests(slowAckThresholdMs); | |
| 295 | 301 | const transport = new WsTransport("ws://localhost:3020"); |
| 296 | 302 | |
| 297 | 303 | const requestPromise = transport.request((client) => |
| ... | ... | @@ -320,7 +326,7 @@ describe("WsTransport", () => { |
| 320 | 326 | tag: WS_METHODS.serverUpsertKeybinding, |
| 321 | 327 | }, |
| 322 | 328 | ]); |
| 323 | }, 5_000); | |
| 329 | }, 1_000); | |
| 324 | 330 | |
| 325 | 331 | socket.serverMessage( |
| 326 | 332 | JSON.stringify({ |
| ... | ... | @@ -343,7 +349,7 @@ describe("WsTransport", () => { |
| 343 | 349 | expect(getSlowRpcAckRequests()).toEqual([]); |
| 344 | 350 | |
| 345 | 351 | await transport.dispose(); |
| 346 | }, 10_000); | |
| 352 | }, 5_000); | |
| 347 | 353 | |
| 348 | 354 | it("sends unary RPC requests and resolves successful exits", async () => { |
| 349 | 355 | const transport = new WsTransport("ws://localhost:3020"); |