From 8f40c0b6dce67cefa1edce0b865c9a3885d39717 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sat, 15 Aug 2026 09:42:27 +0200 Subject: fix(status): count threads as they arrive instead of "Searching..." Item 74. runQuery() set the status bar once and only queryFinished cleared it, so the bar kept claiming a query was running for the whole walk while rows were visibly arriving behind it. Measured cold against a 1.1 GB index: the first batch reaches the model at 642 ms and the walk finishes at 5714 ms, so five seconds of a slow query read as a frozen one. onThreadsReady now sets the bar from the model's own row count after each batch, which is the number of rows the user can actually see. No timing changes; this only stops the bar from lying. The refresh branch returns before the new line, so a background refresh stays silent exactly as onQueryFinished already keeps it. That silence has its own test, which fails when the write is moved above the guard. beginRefreshForTesting() is a new seam: refreshCurrentQuery() returns early without a worker and a bare window has none, so a test cannot otherwise reach the refresh path. --- .../plans/2026-08-03-post-0.1.0-usability.md | 47 +--------------------- 1 file changed, 1 insertion(+), 46 deletions(-) (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md') diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md index e1ea2da..841ee91 100644 --- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md +++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md @@ -140,7 +140,7 @@ taking that too literally. | 71 | A toolbar action does not sync, so the edit sits until the next cron run | workflow | S | **done** 2026-08-11; 2s default, `auto_sync_delay_ms` | | 72 | No khard/khal integration | workflow | ? | open, unspecified; the user places it after send, so v2 at the earliest | | 73 | This backlog is past four thousand lines | maintenance | S | **done** 2026-08-13; 5056 lines to 578, closed sections moved to `2026-08-03-post-0.1.0-usability-closed.md` | -| 74 | "Searching..." keeps claiming a query is running while rows are already arriving | feedback | XS | open; cause measured 2026-08-11, the delay itself is the cold page cache and is not fixable here | +| 74 | "Searching..." keeps claiming a query is running while rows are already arriving | feedback | XS | **done** 2026-08-15, unreleased. The status-bar half only: the bar now counts threads per batch. The cold-cache delay itself was measured in 2026-08-11 and is not fixable here | | 75 | The tagging rules window forgets its size and its column widths | persistence | S | **done** 2026-08-13, shipped in 0.17.0. The window-kind question is left open, see the closed-items file | | 76 | Every field in the rules dialog is free text, so a rule is easy to get wrong | workflow | M | **done** 2026-08-13, shipped in 0.17.0. See `specs/2026-08-13-rule-builder-design.md` | | 77 | No way to see what a rule would collect, in the thread list | workflow | S | **done** 2026-08-13, shipped in 0.17.0 | @@ -440,51 +440,6 @@ Those are three different features. **Size: `?`, unspecified**, and out of scope until v2 exists. Ask before designing anything. -## 74. The first query after boot sits on "Searching..." for seconds - -**Observed (user, 2026-08-11):** the first start of the day takes noticeably -longer to show its default view, and the delay happens while the status bar -reads "Searching...". - -**Cause: the notmuch index paging in from disk, not this application's code.** -Measured by instrumenting `main()`, the `MainWindow` constructor and -`NotmuchWorker::runQuery` behind an environment variable, then running the same -`tag:inbox` query (4444 threads) warm and again after evicting the index from -the page cache with `posix_fadvise(POSIX_FADV_DONTNEED)`: - -| phase | warm | cold | -|---|---|---| -| `notmuch_query_search_threads` returns | 0 ms | 411 ms | -| first batch of 200 reaches the model | 10 ms | 642 ms | -| walk complete, all 4444 threads | 154 ms | 5714 ms | - -A 37x difference over the identical code path. The index measured 1.1 GB. The -in-process startup costs nothing by comparison: `QApplication` in 20 ms, the -whole `MainWindow` constructor in ~120 ms, and the window is shown and -interactive at ~196 ms in both the warm and the cold run. - -**There is nothing to fix in the query path**, and the measurement exists mainly -so this is not re-investigated. Two things it did establish that are worth -keeping. The default startup view is whichever saved query `startup_query` names, -defaulting to `Unread`, so a user with an empty unread view never sees this at -all and a user whose default is Inbox always does. And batching already works: -rows land from 642 ms cold, long before the 5714 ms finish. - -**The one real defect it exposed is the status bar.** "Searching..." is set once -in `runQuery` and cleared only on `queryFinished`, so it keeps claiming the -query is running for the full 5.7 s while rows are visibly arriving behind it. -That makes a slow query read as a frozen one. The fix is to update the text per -batch with the count so far rather than holding one string, which changes no -timing and only stops the bar from lying. - -**The user declined this on 2026-08-11**, having asked for the explanation -rather than a change. Recorded as open because the status bar is still -inaccurate, not because anything is expected to happen. - -**Size: XS** for the status bar. The cold-cache cost itself is not addressable -here and should not be attempted: prefaulting 1.1 GB at startup to make one -query look fast is a worse trade than the wait. - ## 78. No way to build a rule from something visible in a message **Observed.** The user would like to select an address or another piece of a -- cgit v1.2.3