mirror of
https://github.com/spartanz51/tutabridge.git
synced 2026-06-24 10:54:32 +02:00
Drop the last two timers: prefetch and the UI stats poll go event-driven
Phase 2.5 — `prefetch_loop` no longer wakes every 30s. It subscribes to `MailStore::subscribe()` and only catches up missing bodies when the generation counter ticks (event-bus delta, sync_folder finishing, bootstrap). When the store is quiet — every cached mail has its .eml on disk — the loop sleeps indefinitely on the watch channel. The `PREFETCH_INTERVAL` constant is gone. Phase 2.6 — the dashboard 1s `setInterval` is gone too. `BridgeHandle` gets a `stats_dirty_tx: broadcast::Sender<()>` that pulses on every `MailStore` bump, every `WsState` transition, and the start / stop status transitions. A small watcher task inside `start()` plumbs the two `watch::Receiver`s into the broadcast. The Tauri layer (`stream_stats`) subscribes via `BridgeHandle::subscribe_stats()`, takes a stats + status snapshot on every pulse (and once at startup), and emits two events `bridge://stats` / `bridge://status` to the webview. The React hook replaces `setInterval(refresh, 1000)` with two `listen()` subscriptions; the initial `refresh()` still seeds the state for the first frame. Backend now has zero `time::sleep`-driven polling loops: the syncer is driven by Phase 0 + bootstrap + the event bus, prefetch is driven by store changes, and the UI is driven by pushes. The only remaining delays are throttling (`INTER_FOLDER_DELAY`, `INTER_REQUEST_DELAY`) and reconnect backoff, which are not polls. 166 bridge lib tests, full workspace builds, UI tsc clean.
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import type { Config, BridgeStatus, BridgeStats } from "../types";
|
||||
|
||||
const MAX_LOG_LINES = 500;
|
||||
const POLL_INTERVAL = 1000;
|
||||
|
||||
export function useBridge() {
|
||||
const [config, setConfig] = useState<Config | null>(null);
|
||||
@@ -18,7 +17,6 @@ export function useBridge() {
|
||||
const [bridgePassword, setBridgePassword] = useState<string | null>(null);
|
||||
const [logs, setLogs] = useState<string[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
invoke<BridgeStatus>("get_status").then(setStatus);
|
||||
@@ -31,9 +29,13 @@ export function useBridge() {
|
||||
invoke<string | null>("get_bridge_password").then(setBridgePassword);
|
||||
refresh();
|
||||
|
||||
pollRef.current = setInterval(refresh, POLL_INTERVAL);
|
||||
// The bridge pushes `bridge://stats` and `bridge://status` whenever
|
||||
// anything changes (mail count, ws state, start/stop). No setInterval.
|
||||
const unlistenStats = listen<BridgeStats>("bridge://stats", (e) => setStats(e.payload));
|
||||
const unlistenStatus = listen<BridgeStatus>("bridge://status", (e) => setStatus(e.payload));
|
||||
return () => {
|
||||
if (pollRef.current) clearInterval(pollRef.current);
|
||||
unlistenStats.then((fn) => fn());
|
||||
unlistenStatus.then((fn) => fn());
|
||||
};
|
||||
}, [refresh]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user