animedex.cache.sqlite
SQLite-backed TTL cache for backend responses.
The cache is the project’s canonical storage for upstream responses; it is consulted before any HTTP call and populated after one. The shape is:
Rows are keyed by
(backend, signature).The body is stored as raw bytes; pydantic models are persisted as
model.model_dump_json().encode("utf-8")and re-hydrated withModel.model_validate_json(raw.decode()).Each row carries a TTL (seconds-since-epoch
expires_at); a row whoseexpires_atis in the past is treated as missing.
The defaults in default_ttl_seconds() come from
plans/03 §10: 72 h for metadata, 24 h for list pages, 1 h for
schedule / trending, 30 d for offline dumps. Anything else gets the
“metadata” default.
The clock primitive (_utcnow) and the cache-dir resolver
(_user_cache_dir) are pulled through indirection points so
unit tests can substitute deterministic fakes without monkeypatching
the standard library globally.
SqliteCache
- class animedex.cache.sqlite.SqliteCache(path: Path | str | None = None)[source]
Bases:
objectA small SQLite-backed cache with per-row TTL.
- Parameters:
path (pathlib.Path or str or None) – Filesystem path to the SQLite database file. Defaults to
default_cache_path().
- __enter__() SqliteCache[source]
- set(backend: str, signature: str, payload: bytes, *, ttl_seconds: int) None[source]
Store or overwrite a row (v1 wrapper).
Exists for callers that don’t need the v2 metadata. Internally delegates to
set_with_meta()withresponse_headers={}, so a subsequentget_with_metareturns a valid row withfetched_at=nowand an empty headers dict.- Parameters:
- Returns:
None.- Return type:
None
- set_with_meta(backend: str, signature: str, payload: bytes, *, response_headers: Dict[str, str], ttl_seconds: int) None[source]
Store or overwrite a row with v2 metadata.
- Parameters:
backend (str) – Backend identifier.
signature (str) – Caller-derived row signature.
payload (bytes) – Raw bytes to store.
response_headers (dict[str, str]) – Response headers dict; persisted as JSON-encoded bytes so cache hits in
--debugmode can reconstruct the full envelope.ttl_seconds (int) – Lifetime in seconds.
- Returns:
None.- Return type:
None
- get(backend: str, signature: str) bytes | None[source]
Look up a row.
Returns the payload if the row exists and has not expired;
Noneotherwise. Expired rows are not deleted on read (usepurge_expired()for that) so a singlegetstays a pure read.
default_ttl_seconds
- animedex.cache.sqlite.default_ttl_seconds(category: str) int[source]
Return the project-default TTL for a request category.
Per
plans/03 §10:metadata: 72 hlist: 24 hschedule/trending: 1 hoffline_dump: 30 d
Unknown categories collapse to the metadata default; this keeps the cache useful for one-off entries without forcing every call site to declare a category.
default_cache_path
- animedex.cache.sqlite.default_cache_path() Path[source]
Resolve the platform-appropriate cache file path.
Uses
platformdirs.user_cache_dir()(via the_user_cache_dirindirection) so the location matches the OS convention:~/.cache/animedexon Linux,~/Library/Caches/animedexon macOS, the appropriateLOCALAPPDATAsubtree on Windows.- Returns:
Path to
cache.sqliteinside the cache dir.- Return type:
selftest
- animedex.cache.sqlite.selftest() bool[source]
Smoke-test the SQLite cache.
Builds a temporary cache file under
_user_cache_dir, writes a row, reads it back, lets the test-supplied clock advance past the TTL, and confirms expiry. Cleans up the temporary file before returning.- Returns:
Trueon success.- Return type: