Skip to main content

Module cache

Module cache 

Source
Expand description

The read-only browse cache: the Cache storage trait plus the CacheHandle every service call goes through.

The library owns no storage. An embedder passes an Arc<dyn Cache> to Context::new: the CLI uses SqliteCache (crate grabcli-sqlite, one SQLite database with FTS5 under the cache dir), tests use MemoryCache, and an embedder that wants no cache uses NoCache. A cache stores three things:

  • Responses: the raw upstream JSON of read-only calls (search results, menus, store details, category lists), keyed by the SHA-256 of a canonical request identity (CacheKey) that includes the rounded delivery location. Raw responses (not parsed structs) are stored so struct changes never change what an entry means. TTLs, modes and freshness are applied by CacheHandle, not by the backend.
  • Catalog: normalized, queryable restaurants, where they were seen from, menu categories and menu items (types). Service crates upsert into it whenever they fetch list or menu data, and query it for offline (--local) search.
  • Images: item images by URL (CachedImage), optional.

The cache is best-effort: a backend error on a read is a miss and a failed write is skipped. A broken cache never fails a browse command.

The trait is async (async_trait) for the same reason as SessionStore: the context is async and a backend may be an async database client.

§Safety: what may be cached

Only the read-only kinds in CacheKind exist, and every cached call must pick one. There is deliberately no kind for quotes, carts, vouchers, auth/session/token responses, order submission, order history or tracking: those must always be fetched live, and adding a kind for them is a safety regression. The catalog likewise only holds restaurant, menu and item data. Commands on the cart → quote → order path use CacheMode::Off (or call the API directly) so prices and availability are always fresh before money moves; with the mode off nothing is read from or written to any part of the cache.

§Usage from a service crate

ⓘ
let key = CacheKey::new("food", CacheKind::Menu, "merchant")
    .param("id", merchant_id)
    .location(loc.latitude, loc.longitude);
let raw: serde_json::Value = ctx.cached_call(&key, &req).await?;
// with the entry's age (for "(cached 4m ago)" markers):
let hit = ctx.cached_call_meta(&key, &req).await?;
// or, for anything that isn't a single request:
let cache = ctx.cache().clone();
let raw: serde_json::Value = cache.get_or_fetch(&key, || ctx.call(&req)).await?;

Re-exports§

pub use memory::MemoryCache;
pub use memory::NoCache;
pub use types::CachedImage;
pub use types::CategoryRow;
pub use types::ItemHit;
pub use types::ItemQuery;
pub use types::ItemRow;
pub use types::Near;
pub use types::RestaurantHit;
pub use types::RestaurantQuery;
pub use types::RestaurantRow;
pub use types::effective_price;
pub use types::haversine_km;
pub use types::image_url_allowed;
pub use types::query_terms;

Modules§

memory
In-memory Cache backends: MemoryCache (everything in maps, for tests and short-lived embedders) and NoCache (stores nothing).
types
Plain data the Cache trait stores and returns: catalog rows, queries and hits, and cached images. No storage here.

Structs§

CacheConfig
[cache] in config.toml. Every key is optional.
CacheEntry
One stored response, as a backend keeps it.
CacheHandle
A Cache backend plus the active CacheMode and TTLs. Cheap to clone (clones share the backend); clone it out of the Context to call get_or_fetch with a closure that borrows the context.
CacheKey
The identity of a cached request: service namespace, kind, endpoint name and normalized parameters. Two keys with the same identity share an entry.
CacheTtls
Per-kind TTL overrides in seconds.
Fetched
A value plus where it came from: cached_at is the time the cached response was fetched, or None if it was just fetched live.

Enums§

CacheKind
What is being cached. Only read-only browse data has a kind; see the module docs before adding one.
CacheMode
How a command uses the cache.

Constants§

DEFAULT_IMAGE_MAX_MB
Default image store cap ([cache] image_max_mb).
DEFAULT_INDEX_MAX_AGE_DAYS
Default age after which grab cache prune drops catalog rows.
NO_CACHE_ENV
Environment variable the CLI reads to disable the cache (truthy value). The library itself never reads the environment. Environment variable that disables the cache when set to a truthy value.

Traits§

Cache
Storage for the read-only browse cache. Object-safe: use it as Arc<dyn Cache>. Backends store and return data; TTLs, modes and the read-only safety rules are applied by CacheHandle.

Functions§

hex_sha256
human_age
4m, 2h, 3d — for “(cached 4m ago)” markers.
is_fresh
round_coord_to