claude-memory/graph/code-patterns/two-phase-cached-loading-pattern-for-api-heavy-screens-in-ru-77c0b8.md

57 lines
2.0 KiB
Markdown

---
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:20.017854+00:00"
relations:
- target: 1d64c80d-61ec-434f-902a-3a511e2b92c2
type: RELATED_TO
direction: outgoing
strength: 0.71
edge_id: 971778f6-4161-4ae3-be07-44f5e4645577
- target: fc4eb194-1b19-4bb7-8b63-97ae30c8a3e0
type: RELATED_TO
direction: outgoing
strength: 0.72
edge_id: a78f60a1-1597-4b18-835d-c6bc8d97c535
- target: e5ec55be-ced4-4c30-8390-940b45dc2ed5
type: RELATED_TO
direction: outgoing
strength: 0.7
edge_id: 8e624197-1bd1-49cd-9082-437551829431
---
# 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<AppMessage>`
- 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.