Basic usage:
from zoocache import cacheable, invalidate, add_deps
@cacheable
def get_product_page(pid: int, sid: int):
product = db.get_product(pid)
add_deps([f"product:{pid}"])
stock = db.get_stock(sid, pid)
add_deps([f"store:{sid}:stock"])
return render(product, stock)
get_product_page(42, 1) # computes and caches
get_product_page(42, 1) # cache hit
invalidate("product:42") # product info changed
invalidate("store:1") # clears ALL store:1:* (stock, prices, etc)
Tags are hierarchical, invalidating a parent like "store:1" clears everything under it. No scanning or pattern matching needed.Internally it's a prefix trie with HLC for distributed consistency, a SingleFlight to avoid thundering herds, and MsgPack+LZ4 serialization. The core is Rust via PyO3. Supports in-memory, LMDB, and Redis backends.
It's a fairly niche tool, if simple TTL or lru_cache covers your use case, you don't need this. It's more for when you have complex data relationships and need precise, immediate invalidation.
Source: https://github.com/albertobadia/zoocache
Hope you find it useful. Happy to receive feedback, PRs, or discuss design tradeoffs.