Commit 2d9d763
feat: live bottleneck indicator on the Activity dashboard (#311)
## Summary
Closes #308.
Backend classifier (new `src-tauri/src/bottleneck_hub.rs`, 1s cadence,
idle
suppression) that names the current limiting pipeline stage:
`not_backing_up` / `disk` / `network` / `api` / `cpu` / `mixed`. Streams
as a
new `sync:bottleneck` event with a `bottleneck_status` hydration
command.
**Heuristic** (documented in `classify()`'s doc comment, unit-tested
over all
six states + boundary cases):
1. No account mid-cycle => `not_backing_up`.
2. A mid-cycle account's rate pacer is backing off (or the orchestrator
itself is in the `Backoff` circuit-breaker state) => `api`, naming the
destination + remaining ms. Checked before rates because a paced account
can otherwise show misleadingly healthy numbers between gated requests.
3. Otherwise compare disk-read / net-wire-accepted / blake3-hashed
bytes/sec.
Stages at or below a 32 KB/s idle floor are dropped from consideration.
Among the remaining active stages, the slowest is the bottleneck,
provided the fastest active stage clears it by >= 1.5x; short of that
there's no clear winner => `mixed`.
**Signals wired in:**
- Disk/net rates: existing `IoCounters`
(`crates/driven-core/src/iostat.rs`),
diffed by the sampler - untouched by the AdaptiveController's separate
drain-based `ThroughputProbe`.
- `api`: new public `AimdPacer::backoff_remaining_ms()` getter
(non-blocking
read of the private `backoff_until_ms` deadline against the injected
clock), exposed through the `Pacer` trait (default `None`) and two new
default `Orchestrator` trait methods (`pacer_backoff_remaining_ms`,
`backend_label`) so the sampler can poll every account's orchestrator
through its existing `Arc<dyn Orchestrator>` handle with no structural
changes to orchestrator.rs/executor.rs.
- `cpu`: net-new cumulative hash-byte counter added alongside
`IoCounters`'
existing disk/net fields (`IoCounters::add_hashed`), credited from the
upload pipeline's `cpu_stage` (streamed path) and `inline_upload`
(buffered small-file path), plus the scanner's deep-verify re-hash
(threaded through a new optional `io_counters` param on
`scan_with_priority`). A relaxed atomic add on the existing counter -
no new hot-path allocation.
## Frontend
- `BottleneckStatTile.vue`: a plain-value sibling of
`ThroughputStatTile`
(same `STAT_TILE` chrome, `dt`/`dd` typography); no sparkline since the
backend classifies one current state, not a series.
- `stores/bottleneck.ts`: subscribe()/hydrate() pattern like
`stores/iostat.ts`,
plus a debounce/hysteresis gate - a new state must hold for 5s (measured
off the snapshots' own `tsMs`, not `Date.now()`, so it's deterministic
under test) before the tile adopts it, so brief flapping never reaches
the
UI.
- Activity stat grid: 7 tiles now (Bottleneck joined), so both the real
grid
and its loading skeleton moved to `lg:grid-cols-6` (previously
mismatched
at 5 vs 6).
- README: mentions the new tile where the Activity dashboard's features
are
listed.
## Test plan
- [x] `cargo test -p driven-core -p driven-app --lib` - 557 + 455 passed
- [x] `cargo clippy -p driven-core -p driven-app --all-targets -- -D
warnings` - clean
- [x] `cargo fmt --check` - clean
- [x] `pnpm -C ui run test:unit` - 805 passed (61 files), including new
`bottleneck-store.test.ts` (7 tests) and `bottleneck-stat-tile.test.ts`
(9 tests)
- [x] `npx vue-tsc --noEmit` / `eslint` / `prettier --check` - clean
- [x] Visual baselines regenerated via the `just visual-update` Docker
image,
scoped to `activity.spec.ts` (light/dark x populated/empty/loading;
`error.png` unchanged) - screenshots reviewed, tile renders correctly
in both themes at the new 6-column grid.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 7e87341 commit 2d9d763
29 files changed
Lines changed: 1888 additions & 16 deletions
File tree
- crates/driven-core/src
- src-tauri/src
- commands
- ui
- e2e-visual/__screenshots__/linux
- dark/activity.spec.ts
- light/activity.spec.ts
- src
- __tests__
- components
- ipc
- locales
- stores
- views
- test-support
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
180 | 180 | | |
181 | 181 | | |
182 | 182 | | |
183 | | - | |
| 183 | + | |
184 | 184 | | |
185 | 185 | | |
186 | | - | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
187 | 189 | | |
188 | 190 | | |
189 | 191 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2746 | 2746 | | |
2747 | 2747 | | |
2748 | 2748 | | |
| 2749 | + | |
| 2750 | + | |
| 2751 | + | |
| 2752 | + | |
2749 | 2753 | | |
2750 | 2754 | | |
2751 | 2755 | | |
| |||
2862 | 2866 | | |
2863 | 2867 | | |
2864 | 2868 | | |
2865 | | - | |
| 2869 | + | |
2866 | 2870 | | |
2867 | 2871 | | |
2868 | 2872 | | |
| |||
7292 | 7296 | | |
7293 | 7297 | | |
7294 | 7298 | | |
| 7299 | + | |
| 7300 | + | |
| 7301 | + | |
| 7302 | + | |
7295 | 7303 | | |
7296 | 7304 | | |
7297 | 7305 | | |
7298 | 7306 | | |
7299 | 7307 | | |
7300 | 7308 | | |
7301 | 7309 | | |
7302 | | - | |
| 7310 | + | |
| 7311 | + | |
| 7312 | + | |
7303 | 7313 | | |
7304 | 7314 | | |
7305 | 7315 | | |
7306 | 7316 | | |
7307 | 7317 | | |
7308 | 7318 | | |
| 7319 | + | |
| 7320 | + | |
| 7321 | + | |
7309 | 7322 | | |
7310 | 7323 | | |
7311 | 7324 | | |
| |||
13265 | 13278 | | |
13266 | 13279 | | |
13267 | 13280 | | |
| 13281 | + | |
| 13282 | + | |
| 13283 | + | |
| 13284 | + | |
| 13285 | + | |
| 13286 | + | |
| 13287 | + | |
| 13288 | + | |
| 13289 | + | |
| 13290 | + | |
| 13291 | + | |
| 13292 | + | |
| 13293 | + | |
| 13294 | + | |
| 13295 | + | |
| 13296 | + | |
| 13297 | + | |
| 13298 | + | |
| 13299 | + | |
| 13300 | + | |
| 13301 | + | |
| 13302 | + | |
| 13303 | + | |
| 13304 | + | |
| 13305 | + | |
| 13306 | + | |
| 13307 | + | |
| 13308 | + | |
| 13309 | + | |
| 13310 | + | |
| 13311 | + | |
| 13312 | + | |
| 13313 | + | |
| 13314 | + | |
| 13315 | + | |
| 13316 | + | |
| 13317 | + | |
| 13318 | + | |
| 13319 | + | |
| 13320 | + | |
| 13321 | + | |
| 13322 | + | |
| 13323 | + | |
| 13324 | + | |
| 13325 | + | |
| 13326 | + | |
| 13327 | + | |
| 13328 | + | |
| 13329 | + | |
| 13330 | + | |
| 13331 | + | |
| 13332 | + | |
| 13333 | + | |
| 13334 | + | |
| 13335 | + | |
| 13336 | + | |
| 13337 | + | |
| 13338 | + | |
| 13339 | + | |
13268 | 13340 | | |
13269 | 13341 | | |
13270 | 13342 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
24 | 32 | | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
| 33 | + | |
| 34 | + | |
29 | 35 | | |
30 | 36 | | |
31 | 37 | | |
| |||
36 | 42 | | |
37 | 43 | | |
38 | 44 | | |
| 45 | + | |
39 | 46 | | |
40 | 47 | | |
41 | 48 | | |
| |||
45 | 52 | | |
46 | 53 | | |
47 | 54 | | |
| 55 | + | |
| 56 | + | |
48 | 57 | | |
49 | 58 | | |
50 | 59 | | |
| |||
58 | 67 | | |
59 | 68 | | |
60 | 69 | | |
61 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
62 | 79 | | |
63 | 80 | | |
64 | 81 | | |
65 | 82 | | |
| 83 | + | |
66 | 84 | | |
67 | 85 | | |
68 | 86 | | |
| |||
78 | 96 | | |
79 | 97 | | |
80 | 98 | | |
81 | | - | |
| 99 | + | |
| 100 | + | |
82 | 101 | | |
83 | 102 | | |
84 | 103 | | |
85 | 104 | | |
86 | 105 | | |
| 106 | + | |
87 | 107 | | |
88 | 108 | | |
89 | 109 | | |
| 110 | + | |
90 | 111 | | |
91 | 112 | | |
92 | 113 | | |
| |||
0 commit comments