fire-planner/fire_planner/api
Viktor Barzin 4da58fe56e
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fire-planner: lazy-refresh /networth from wf_sync (default TTL 1d)
The account_snapshot cache fed /networth, /networth/history, and
/scenarios/{id}/progress. No CronJob populated it, so the cache had
drifted ~18 days behind the wealthfolio_sync mirror (last refresh
2026-05-09 via manual kubectl exec; Grafana reads wf_sync directly
and stayed fresh).

Switch to lazy refresh on read: each request to those endpoints now
checks MAX(account_snapshot.snapshot_date) — if it's older than
NETWORTH_CACHE_TTL_DAYS (default 1), pull fresh rows from wf_sync via
read_account_snapshots_from_pg and upsert. Idempotent under
concurrency (existing ON CONFLICT DO UPDATE).

Plumbing:
- Add get_wf_sync_session dependency that yields None when the wf_sync
  factory isn't wired (keeps existing tests' behaviour: no refresh
  attempted, they continue to seed account_snapshot directly).
- Wire wf_sync engine + session_factory in app.lifespan when
  WEALTHFOLIO_SYNC_DB_CONNECTION_STRING is set.
- Centralise the staleness check in refresh_account_snapshots_if_stale.

Tests:
- 271 existing tests still green.
- Three new tests in test_api_networth_refresh.py covering: empty cache
  triggers refresh, stale cache triggers refresh, fresh cache skips
  refresh (asserts the wf_sync value is NOT served).
2026-05-27 18:21:12 +00:00
..
__init__.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
auth.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
cashflow.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
dependencies.py fire-planner: lazy-refresh /networth from wf_sync (default TTL 1d) 2026-05-27 18:21:12 +00:00
goals.py api: drop bearer-token gate from /api/* CRUD + simulate 2026-05-09 23:56:37 +00:00
income_streams.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
life_events.py api: drop bearer-token gate from /api/* CRUD + simulate 2026-05-09 23:56:37 +00:00
networth.py fire-planner: lazy-refresh /networth from wf_sync (default TTL 1d) 2026-05-27 18:21:12 +00:00
progress.py fire-planner: lazy-refresh /networth from wf_sync (default TTL 1d) 2026-05-27 18:21:12 +00:00
scenarios.py fire-planner: UX review pass 1 — fix sidebar/route/PATCH/badges issues 2026-05-10 17:17:55 +00:00
schemas.py col: simulator auto-adjusts spending to local prices via Numbeo+Expatistan 2026-05-22 14:14:57 +00:00
simulate.py col: simulator auto-adjusts spending to local prices via Numbeo+Expatistan 2026-05-22 14:14:57 +00:00
spending.py whatif: live data refresh, inflation-adjusted spending, legend fix 2026-05-10 11:27:22 +00:00
spending_profile.py fire-planner: What-If gains the chart-first scenario editor 2026-05-12 19:35:28 +00:00
year_stats.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00