fix: read user settings fresh instead of from a per-process cache
The user settings service kept a 5-minute cache in each API process, and the API container runs two gunicorn workers (WEB_CONCURRENCY defaults to 2 in the Dockerfile). A read that landed on the other worker after an update returned the old settings for up to 5 minutes. An update handled there merged onto that stale copy too, so its response could carry an old theme. I hit it while checking #333 in a browser: right after toggling the theme, the GET sometimes answered with the previous one. Once #333 merges, the frontend applies the theme from the settings query on every refetch, so this would show as a theme flipping back.
Every read now rebuilds from the latest snapshot and the events after it. That's two MongoDB queries and at most ten events, since a snapshot is written every ten. cachetools had no other user, so it's dropped from the dependencies.
The new unit test runs two services over one store, standing in for two workers, and fails on main (auto == dark). The e2e test that only checked the cache hit is replaced by one that reads right after an update. Unit tests, ruff, mypy and the orphan check pass. The non-k8s e2e suite passes apart from the usual k3s-only saga, notification and SSE tests.
Summary by cubic
Fixes stale user settings when an update goes through one API worker and a read hits another, since each worker kept its own 5-minute cache. Reads now rebuild from the latest snapshot and the events after it, so updates are visible immediately; updates no longer merge onto a stale cached copy.
- Removed the per-process TTLCache and the now-unused
cachetoolsandtypes-cachetoolsdependencies. - Each read costs two MongoDB queries and at most ten events, since a snapshot follows every ten.
- Replaced the e2e cache-hit test with one that reads right after an update, and added a unit test where a second service stands in for another worker.
- Updated architecture docs to match.