Overview deadline flushes a fast key before its settle window
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- react, typescript
- Domain
- frontend
Research direction
Start with web/src/useKbEvents.ts, especially the overview timer and the shared invalidation coalescer described in the issue. Trace how fast keys and the overview key are queued, then check the related tests if available. Done means an overview deadline no longer invalidates fast keys before their 300 ms settle period, while explicit unmount and reconnect flushes still work.
Written by the indexing model from the issue text.
Description
- Repository:
deeplethe/utopia - Target commit:
fa77a956797e86fc0465971d890c59b85ee971ec - File:
web/src/useKbEvents.ts:6-31
Summary
overview deadline flushes a fast key before its settle window.
Root cause
The overview timer uses the shared coalescer and forces a global flush instead of invalidating only the overview key.
Affected code
web/src/useKbEvents.ts:
1 // KB 事件流订阅:收到事件只做 react-query 失效重取(事件不带业务数据,天然幂等)。
2 // EventSource 断线自动重连,重连成功后补刷漏掉的变化;替代 Library/Review 的轮询。
3 // 告警也从这条流来:一页只占一条通知用的连接(见 `eventStream`)。
4 //
5 // **失效是合并着做的。** 一篇文档抽取时每落一条事实就发一个 graph 事件,
6 // 从前每个事件各失效一次,图谱页在那几秒里把 overview 重取了十几遍——
7 // 每次都是同一张图,最后一次才算数。所以事件只把 key 记下来,停顿一小会
8 // 再一次性失效:一阵事件只换来一次重取,最后那次一定包含之前所有的变化。
9 // 幂等性没变,只是把「每条都刷」变成「刷最后一条」。
10 //
11 // 失效不看 staleTime:这里失效的键在 queryDefaults.ts 里放到了 30 秒,靠的就是
12 // 这一层把当前库的变化即时推到页面上。
13 import { useEffect } from "react";
14 import { partialMatchKey, useQueryClient, type QueryKey } from "@tanstack/react-query";
15 import { subscribeEvents } from "./eventStream";
16 import { STREAM_KEYS } from "./queryDefaults";
17
18 /** 一阵事件之间的静默期。抽取落事实的间隔远小于它,人眼看不出这点延迟 */
19 export const SETTLE_MS = 300;
20
21 /** 全图 overview 要数遍整个库:推送期间几秒重数一次就够了(#1296) */
22 export const OVERVIEW_SETTLE_MS = 3_000;
23
24 /**
25 * 把一阵失效合并成一次:`push` 只记键,静默 `settleMs` 后一起交给 `invalidate`,
26 * 同一个键及其前缀只失效一次;`flush` 给卸载与重连用,攒着的刷掉而不是丢掉。
27 * 抽成纯函数是为了能测;订阅那层只是把事件名映射到键。
28 */
29 export function createInvalidationCoalescer(
30 invalidate: (key: QueryKey) => void,
31 settleMs: number,
32 ) {
33 const pending = new Map<string, QueryKey>();
34 let timer: ReturnType<typeof setTimeout> | null = null;
35 const flush = () => {
36 if (timer !== null) {
37 clearTimeout(timer);
38 timer = null;
39 }
40 const keys = [...pending.values()];
41 pending.clear();
42 for (const key of keys) {
43 // 正常 graph 事件可能已排了 ["graph", kbId, "neighborhood"],重连又补上 ["graph", kbId]:
44 // 前缀已经覆盖后者,不能取消刚开始的请求再重取一遍。
45 if (keys.some((prefix) => prefix.length < key.length && partialMatchKey(key, prefix))) continue;
46 invalidate(key);
47 }
48 };
49 const push = (...keys: QueryKey[]) => {
50 for (const key of keys) pending.set(JSON.stringify(key), key);
51 if (timer === null) timer = setTimeout(flush, settleMs);
52 };
53 return { push, flush };
54 }
55
56 export function useKbEvents(kbId: string | undefined) {
Expected behavior
Fast coalescer pending keys must wait for SETTLE_MS or an explicit unmount/reconnect flush; an overview deadline must not flush unrelated fast pending keys early.
Actual behavior
In web/src/useKbEvents.ts lines 65-68, the overview timer calls push(key); flush(); when it fires, causing all pending fast keys to be invalidated immediately before the fast SETTLE_MS quiet period.
Steps to reproduce
- Arm the overview deadline and enqueue a fast key shortly before it fires.
- Measure the time between the fast event and its invalidation.
- Compare with a fast event with no overview deadline.
Suggested fix
Give the overview key its own coalescer (or a key-scoped flush) so fast keys keep their settle window.
Impact
Fast keys are invalidated early, causing extra refetches and inconsistent batching.
- Dominant language
- Rust
- Stars
- 8.1k
- Forks
- 1.1k
- Avg merge
- 21h 30m
- Merged PRs (30d)
- 251
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from deeplethe/utopia
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
deeplethe/utopia#1341 · 1 comment ·
Maintainers usually reply within 1 day
-
bug
Difficulty 5/5 Over a week Newbie friendliness 48/100
deeplethe/utopia#1338 · 2 comments ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
deeplethe/utopia#1327 · 2 comments ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
deeplethe/utopia#1322 · 6 comments ·
Maintainers usually reply within 1 day
All issues in deeplethe/utopia
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
calcit-lang/caps#16 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
penso/herdr-gpui#934 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Y-ASLant/ElegantClipboard#178 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
linxiv-dev/linXiv#384 · 1 comment ·
Maintainers usually reply within 1 day
-
priority middle
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
KATO-Hiro/AtCoderClans#12945 ·
Maintainers usually reply within 1 day