Invalidate movie/series/person detail cache on re-ingestion
CI / lint (push) Canceled after 0s
CI / typecheck (push) Canceled after 0s
CI / unit-tests (push) Canceled after 0s
CI / integration-tests (push) Canceled after 0s
CI / container-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s

cached_response() had no write-side invalidation, so re-ingesting an
entity kept serving its pre-ingestion cached response for up to
CACHE_DEFAULT_TTL. Found live: re-ingesting a movie to test the new
company-logo field still showed logo_path: None because the sliding
5-minute cache from earlier testing never expired.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
NixReaper
2026-09-05 07:56:00 -05:00
co-authored by Claude Sonnet 5
parent c03a75989d
commit 2138d4afc3
3 changed files with 146 additions and 9 deletions
+13 -8
View File
@@ -139,15 +139,20 @@ titles. Swapping in `OpenSearchProvider` later means implementing the same
write function catches Redis errors and behaves as a cache miss / no-op
rather than raising, so Redis being down degrades performance, not
correctness. `app/api/deps.py:cached_response()` is the read-through helper
used by the movie/person detail endpoints (the read-heaviest, per section
21). Cache keys are versioned (`aurora:v1:...`) so a response-shape change
(bumping `CACHE_VERSION`) doesn't require a manual flush.
used by the movie/series/person detail endpoints (the read-heaviest, per
section 21). Cache keys are versioned (`aurora:v1:...`) so a response-shape
change (bumping `CACHE_VERSION`) doesn't require a manual flush.
Cache invalidation on write: 0.1 has no write API yet (ingestion writes
directly to Postgres via workers, not through the cached read endpoints), so
there is nothing to invalidate today. The moment a write endpoint exists,
it must call `app/services/cache.py:cache_delete` for the affected keys —
tracked as a Known limitation.
Cache invalidation on write: ingestion is the only write path that touches
cached reads (there's no separate write API in 0.1), and it invalidates —
`app/services/ingestion/runner.py:_run_ingestion` takes a `cache_entity_type`
("movie"/"series"/"person") and, on success, deletes that entity's detail
cache key so the next `GET` reflects the just-completed ingestion instead of
serving a pre-ingestion snapshot for up to `CACHE_DEFAULT_TTL`. This was
found live: re-ingesting a movie to pick up a new company-logo field kept
returning the old response because nothing invalidated the cache. Seasons
and episodes aren't cached, so `run_season_ingestion` passes no
`cache_entity_type`.
## Security (section 22)