From 5c9a51fd1d857dc0b01b124fc0f1634e2cbd20cb Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Sun, 1 Mar 2026 18:33:19 -0600 Subject: [PATCH] store: Two-phase cached loading pattern for API-heavy screens in Rust TUI --- ...tern-for-api-heavy-screens-in-ru-77c0b8.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 graph/code-patterns/two-phase-cached-loading-pattern-for-api-heavy-screens-in-ru-77c0b8.md diff --git a/graph/code-patterns/two-phase-cached-loading-pattern-for-api-heavy-screens-in-ru-77c0b8.md b/graph/code-patterns/two-phase-cached-loading-pattern-for-api-heavy-screens-in-ru-77c0b8.md new file mode 100644 index 00000000000..807438157d2 --- /dev/null +++ b/graph/code-patterns/two-phase-cached-loading-pattern-for-api-heavy-screens-in-ru-77c0b8.md @@ -0,0 +1,40 @@ +--- +id: 77c0b897-4124-432f-84de-700ff82dcde1 +type: code_pattern +title: "Two-phase cached loading pattern for API-heavy screens in Rust TUI" +tags: [sba-scouting, rust, caching, ratatui, async, tokio, sqlx, standings, api, pattern] +importance: 0.8 +confidence: 0.8 +created: "2026-03-02T00:33:19.472159+00:00" +updated: "2026-03-02T00:33:19.472159+00:00" +--- + +# Two-Phase Cached Loading Pattern + +## Context +Implemented for the standings screen in SBA Scout Rust TUI. Should be reused for other API-heavy screens. + +## Pattern + +### Phase 1: Instant cache load on mount +- Load from SQLite cache on `mount()` — instant display +- Cache table (`standings_cache`) stores JSON blob per season with `fetched_at` timestamp +- Show "updated Xm ago" indicator to user + +### Phase 2: Background refresh +- Spawn background `tokio::task` to fetch from live API +- Update DB cache after successful fetch +- Send `StandingsRefreshed` message back to UI via `mpsc::UnboundedSender` +- Show spinner while refreshing + +## Key Implementation Details +- Use `serde::Serialize` on response types for JSON round-trip through DB (`serde_json::to_string` / `from_str`) +- Cache table needs: `season` (key), `data_json` (TEXT), `fetched_at` (DATETIME) +- Handle stale cache gracefully — always show cached data immediately, refresh in background + +## Critical API Shape Gotcha +The Major Domo CLI returns bare arrays, but the actual REST API wraps responses: +```json +{"count": N, "standings": [...]} +``` +Always verify real API response shape, not just CLI output. Mismatched deserialization will silently fail or panic.