Add block-update latency tracking, raw share counters, and shares bar UI

Log ZMQ→mining.notify latency in ckpool (patch 0005), expose a raw
reject counter (patch 0006), and surface both in the dashboard:

- Block latency card shows avg/last ms, wasted work, and block count
- SharesBar component shows session + all-time accepted/rejected with
  a Demon Slayer flame-slash animation on new shares
- Miners card info moved to MinersTable section header
- Latency stats and share counts persist across restarts via kv store
- Removed misleading pool-wide share stats from per-worker/user pages
  (ckpool doesn't expose per-user raw counts)
This commit is contained in:
satoshi
2026-05-11 02:12:16 +03:00
parent e622f1a81a
commit 6acff6280f
14 changed files with 555 additions and 18 deletions
+30 -6
View File
@@ -11,8 +11,6 @@
} from "../format";
const data = $derived(snap.data!);
const miners = $derived(data.clients?.length ?? 0);
const workerCount = $derived(data.workers?.length ?? 0);
const height = $derived(data.chain?.blocks ?? 0);
const poolShare = $derived.by(() => {
@@ -56,6 +54,12 @@
const totalHashes = $derived(data.cumulative_shares * 2 ** 32);
// Block update latency (ZMQ → mining.notify)
const latencyAvg = $derived(data.latency_avg_ms ?? 0);
const latencyLast = $derived(data.latency_last_ms ?? 0);
const latencyCount = $derived(data.latency_count ?? 0);
const staleWork = $derived(data.stale_work_hashes ?? 0);
// Luck: best_share / cumulative_work * 100%.
// 100% = exactly expected, >100% = lucky, <100% = unlucky.
const luckPct = $derived.by(() => {
@@ -109,10 +113,22 @@
</div>
</div>
<div class="card">
<div class="stat-label">Miners</div>
<div class="stat-value">{miners}</div>
<div class="stat-sub">{workerCount} workers · {data.users?.length ?? 0} users</div>
<div
class="card"
title="Time from receiving a new block via ZMQ to pushing mining.notify to all miners. Wasted work = hashes spent mining the old block during this window."
>
<div class="stat-label">Block latency</div>
{#if latencyCount > 0}
<div class="stat-value">{latencyAvg}<span class="unit">ms</span></div>
<div class="stat-sub">
last {latencyLast}ms ·
<span class="wasted">{formatWork(staleWork)} wasted</span>
<span class="stat-dim">({latencyCount} blocks)</span>
</div>
{:else}
<div class="stat-value"></div>
<div class="stat-sub">waiting for the next block</div>
{/if}
</div>
<div class="card">
@@ -171,6 +187,7 @@
<span>{retarget.remaining} blocks · ~{retarget.eta}</span>
</div>
</div>
</section>
<style>
@@ -209,6 +226,13 @@
font-weight: 400;
margin-left: 0.15em;
}
.stat-dim {
color: var(--fg-dim);
font-size: 0.9em;
}
.wasted {
color: var(--bad);
}
.adj.up {
color: var(--good);
}