Skip to content

Cache

grelmicro.cache

Cache.

CacheBackend

Bases: Protocol

Protocol for cache storage backends.

All methods are async because backends typically perform I/O. Backends are pure key-value stores: TTL, eviction, and statistics are managed by TTLCache.

Implementations capture the running event loop on __aenter__ in a _loop attribute so the sync @cached wrapper can dispatch coroutines back into it.

get async

get(*, key: str) -> bytes | None

Get raw bytes by key.

Returns None if the key is missing or expired.

PARAMETER DESCRIPTION
key

Fully qualified cache key, already namespaced by TTLCache.

TYPE: str

set async

set(
    *,
    key: str,
    value: bytes,
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store raw bytes with a TTL in seconds and optional tags.

PARAMETER DESCRIPTION
key

Fully qualified cache key, already namespaced by TTLCache.

TYPE: str

value

Serialized payload to store. Opaque to the backend.

TYPE: bytes

ttl

Time-to-live in seconds. The backend must drop the entry once this many seconds have elapsed since the write.

TYPE: float

tags

Tags to associate with the key. The backend writes the value and the tag membership in one atomic operation.

TYPE: Sequence[str] DEFAULT: ()

get_many async

get_many(*, keys: Sequence[str]) -> dict[str, bytes]

Get raw bytes for many keys at once.

Returns a dict holding only the keys that were found. Missing or expired keys are absent from the result.

PARAMETER DESCRIPTION
keys

Fully qualified cache keys to read.

TYPE: Sequence[str]

set_many async

set_many(
    *,
    items: Mapping[str, bytes],
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store many keys with one TTL and optional tags.

PARAMETER DESCRIPTION
items

Fully qualified key to serialized payload.

TYPE: Mapping[str, bytes]

ttl

Time-to-live in seconds applied to every written key.

TYPE: float

tags

Tags to associate with every written key.

TYPE: Sequence[str] DEFAULT: ()

delete async

delete(*, key: str) -> None

Delete a key and clean its tag membership (no-op if absent).

PARAMETER DESCRIPTION
key

Fully qualified cache key. No-op if absent.

TYPE: str

delete_many async

delete_many(*, keys: Sequence[str]) -> None

Delete many keys and clean their tag membership.

PARAMETER DESCRIPTION
keys

Fully qualified cache keys to delete.

TYPE: Sequence[str]

delete_tags async

delete_tags(*, tags: Sequence[str]) -> None

Delete every key associated with any of the given tags.

PARAMETER DESCRIPTION
tags

Tags whose every member key should be deleted.

TYPE: Sequence[str]

clear async

clear() -> None

Remove all entries managed by this backend.

CacheError

Bases: GrelmicroError

Base cache error.

CacheInfo dataclass

CacheInfo(
    hits: int,
    misses: int,
    maxsize: int,
    currsize: int,
    evictions: int,
)

Cache statistics snapshot.

ATTRIBUTE DESCRIPTION
hits

Number of cache hits.

TYPE: int

misses

Number of cache misses.

TYPE: int

maxsize

Maximum number of entries (0 means unlimited).

TYPE: int

currsize

Current number of tracked entries.

TYPE: int

evictions

Number of entries evicted to make room.

TYPE: int

hits instance-attribute

hits: int

misses instance-attribute

misses: int

maxsize instance-attribute

maxsize: int

currsize instance-attribute

currsize: int

evictions instance-attribute

evictions: int

CacheSerializer

Bases: Protocol[T]

Protocol for cache serialization strategies.

Any object implementing dumps and loads can be used as a TTLCache serializer.

dumps

dumps(value: T) -> bytes

Serialize a value to bytes.

loads

loads(data: bytes) -> T

Deserialize bytes to a value.

CacheSettingsValidationError

CacheSettingsValidationError(error: ValidationError | str)

Bases: CacheError, SettingsValidationError

Cache Settings Validation Error.

JsonSerializer

Serialize values as JSON bytes.

Uses orjson when available (roughly 7x faster than stdlib), otherwise falls back to the standard library json module.

Suitable for dicts, lists, and other JSON-native types. datetime objects are serialized to ISO 8601 strings but deserialized back as strings (not datetime).

dumps

dumps(value: JSONEncodable) -> bytes

Serialize a value to JSON bytes.

loads

loads(data: bytes) -> JSONDecodable

Deserialize JSON bytes to a value.

PickleSerializer

PickleSerializer(*, protocol: int = HIGHEST_PROTOCOL)

Bases: Generic[T]

Serialize values using Python pickle.

Supports any picklable Python object. Fast and transparent, but produces opaque binary data.

Danger

Deserialization can execute arbitrary code. A compromised cache backend can run code inside the application process. Use this serializer only when the backend is fully trusted (in-process, single-tenant). For shared backends (Redis, Memcached, any multi-tenant store), use JsonSerializer or PydanticSerializer instead.

PARAMETER DESCRIPTION
protocol

Serialization protocol version. Defaults to the highest available protocol.

TYPE: int DEFAULT: HIGHEST_PROTOCOL

Initialize the pickle serializer.

dumps

dumps(value: T) -> bytes

Serialize a value to bytes.

loads

loads(data: bytes) -> T

Deserialize bytes to a value.

PydanticSerializer

PydanticSerializer(model: type[T])

Bases: Generic[T]

Serialize values using Pydantic's TypeAdapter.

Uses Pydantic's Rust-based serializer for fast, type-safe roundtrips. Works with BaseModel, dataclass, TypedDict, and any type supported by TypeAdapter.

This is the fastest serialization option (benchmarked at roughly 2x faster than pickle for Pydantic models).

PARAMETER DESCRIPTION
model

The type to serialize/deserialize. Can be any type supported by pydantic.TypeAdapter.

TYPE: type[T]

Initialize the Pydantic serializer.

dumps

dumps(value: T) -> bytes

Serialize a value to JSON bytes via TypeAdapter.

loads

loads(data: bytes) -> T

Deserialize JSON bytes to a typed value via TypeAdapter.

TTLCache

TTLCache(
    maxsize: int = 0,
    ttl: float = 60,
    *,
    backend: CacheBackend | None = None,
    serializer: CacheSerializer[T] | None = None,
)

Bases: Generic[T]

Cache with per-entry TTL and optional LRU eviction.

Delegates storage to a CacheBackend (in-memory, Redis, etc.). TTLCache handles maxsize enforcement, LRU eviction, serialization, and statistics on top of the backend.

When no backend is provided, the registered default is used (see MemoryCacheAdapter or RedisCacheAdapter).

The type parameter T represents the cached value type. Defaults to Any when unspecified (TTLCache()). Use TTLCache[User](serializer=PydanticSerializer(User)) for typed caching.

RAISES DESCRIPTION
ValidationError

If maxsize is negative or ttl is not positive. ValidationError is a subclass of ValueError, so existing except ValueError: blocks still catch it.

Initialize the cache.

PARAMETER DESCRIPTION
maxsize

Maximum number of entries. 0 means unlimited. Only enforced locally (not by the backend).

TYPE: int DEFAULT: 0

ttl

Default TTL in seconds for all entries.

TYPE: float DEFAULT: 60

backend

The cache storage backend.

By default, the registered cache backend is used.

TYPE: CacheBackend | None DEFAULT: None

serializer

Serialization strategy for cached values.

Any object implementing the CacheSerializer protocol (dumps / loads methods) can be used.

Built-in options:

  • PydanticSerializer(Model): Type-safe Pydantic roundtrips.
  • JsonSerializer(): JSON-native types (dict, list, etc.).
  • PickleSerializer(): Any picklable object. Trusted backends only: deserialization can execute arbitrary code.
  • None: Raw bytes only (no serialization).

TYPE: CacheSerializer[T] | None DEFAULT: None

config property

config: TTLCacheConfig

Return the frozen config snapshot.

get async

get(key: str, default: T | None = None) -> T | None

Get a value by key.

Returns the default if the key is missing or expired. A hit promotes the key in LRU order.

PARAMETER DESCRIPTION
key

The cache key.

TYPE: str

default

Value to return if the key is missing or expired.

TYPE: T | None DEFAULT: None

set async

set(
    key: str,
    value: T,
    ttl: float | None = None,
    *,
    tags: Sequence[str] = (),
    stale_ttl: float | None = None,
) -> None

Set a value with an optional per-entry TTL override and tags.

If the cache is full (maxsize > 0), evicts the least recently used entry before storing.

PARAMETER DESCRIPTION
key

The cache key.

TYPE: str

value

The value to store. Must be bytes or serializable.

TYPE: T

ttl

Per-entry TTL override in seconds. Uses the default TTL if None.

TYPE: float | None DEFAULT: None

tags

Tags to associate with the entry. Invalidate every entry sharing a tag at once with delete_tags.

TYPE: Sequence[str] DEFAULT: ()

stale_ttl

Extra seconds to keep a fallback copy of the value past its TTL. When set, get_or_set and @cached serve this stale copy if a later recompute fails, until the extra budget elapses. None (the default) keeps no fallback.

TYPE: float | None DEFAULT: None

RAISES DESCRIPTION
ValueError

If ttl or stale_ttl is not positive.

TypeError

If value is not bytes and no serializer is set.

get_or_set async

get_or_set(
    key: str,
    factory: Callable[[], T] | Callable[[], Awaitable[T]],
    *,
    ttl: float | None = None,
    tags: Sequence[str] = (),
    stale_ttl: float | None = None,
) -> T

Return the cached value, or compute, store, and return it.

On a hit the cached value is returned and a hit is recorded. On a miss the factory runs once under stampede protection, the result is stored with the given ttl and tags, and a miss is recorded by the initial read. Concurrent misses on the same key fold into a single computation, across replicas when a lock backend is configured.

With stale_ttl set, a factory that raises on a miss serves the most recent value (kept for stale_ttl seconds past its TTL) instead of propagating the error.

PARAMETER DESCRIPTION
key

The cache key.

TYPE: str

factory

Sync or async callable that produces the value on a miss. Awaited when it returns a coroutine.

TYPE: Callable[[], T] | Callable[[], Awaitable[T]]

ttl

Per-entry TTL override in seconds. Uses the default if None.

TYPE: float | None DEFAULT: None

tags

Tags to associate with the entry when it is computed.

TYPE: Sequence[str] DEFAULT: ()

stale_ttl

Extra seconds to keep a fallback copy past the TTL. When set and the factory raises on a miss, the most recent value is served instead of propagating the error, until the extra budget elapses. None (default) propagates.

TYPE: float | None DEFAULT: None

get_many async

get_many(keys: Sequence[str]) -> dict[str, T]

Return a dict of found values for the given keys.

Missing or expired keys are absent from the result. Records one hit per found key and one miss per absent key.

PARAMETER DESCRIPTION
keys

The cache keys to read.

TYPE: Sequence[str]

set_many async

set_many(
    mapping: Mapping[str, T],
    *,
    ttl: float | None = None,
    tags: Sequence[str] = (),
) -> None

Store many key to value pairs with one TTL and optional tags.

PARAMETER DESCRIPTION
mapping

Key to value pairs to store.

TYPE: Mapping[str, T]

ttl

Per-entry TTL override in seconds. Uses the default if None.

TYPE: float | None DEFAULT: None

tags

Tags to associate with every stored entry.

TYPE: Sequence[str] DEFAULT: ()

RAISES DESCRIPTION
ValueError

If ttl is not positive.

TypeError

If a value is not bytes and no serializer is set.

delete async

delete(key: str) -> None

Delete a key from the cache.

Also drops the stale-reserve copy, so an explicit delete is never undone by a later stale serve. No-op if the key does not exist.

PARAMETER DESCRIPTION
key

The cache key to delete.

TYPE: str

delete_many async

delete_many(keys: Sequence[str]) -> None

Delete many keys from the cache.

Keys that do not exist are ignored.

PARAMETER DESCRIPTION
keys

The cache keys to delete.

TYPE: Sequence[str]

delete_tags async

delete_tags(*tags: str) -> None

Delete every entry associated with any of the given tags.

Clears the local LRU bookkeeping, since the deleted keys are not known in advance.

PARAMETER DESCRIPTION
*tags

Tags whose every entry should be deleted.

TYPE: str DEFAULT: ()

clear async

clear() -> None

Remove all entries from the cache.

cache_info

cache_info() -> CacheInfo

Return a snapshot of cache statistics.

cached

Cached Decorator.

P module-attribute

P = ParamSpec('P')

R module-attribute

R = TypeVar('R')

cached

cached(
    cache: TTLCache | None = None,
    *,
    ttl: float | None = None,
    maxsize: int = 0,
    key: str | None = None,
    key_maker: Callable[
        [
            Callable[..., Any],
            tuple[Any, ...],
            dict[str, Any],
        ],
        str,
    ]
    | None = None,
    skip: Callable[[Any], bool] | None = None,
    typed: bool = False,
    lock: bool | Literal["local"] = "local",
    early: float | None = None,
    stale_ttl: float | None = None,
    tags: Sequence[str] = (),
) -> Callable[[Callable[P, R]], Callable[P, R]]

Cache decorator for sync and async functions.

Automatically detects whether the decorated function is sync or async and wraps it accordingly.

The decorated function exposes cache_info() and cache_clear() helpers (matching functools.lru_cache). cache_clear() is always a coroutine (must be awaited).

Pass a TTLCache as cache to share one store across functions, invalidate by tag, or override it in tests. For the plain memoize case, omit cache and pass ttl= instead. The decorator then builds a private process-local cache for this function alone.

PARAMETER DESCRIPTION
cache

The TTLCache instance to store results in.

Omit it and pass ttl= instead for the plain memoize case. The decorator then builds a private process-local TTLCache on a MemoryCacheAdapter owned by this function. That private cache never resolves the active app, so its entries live only in this process and are not shared across replicas. Pass a TTLCache when you want a shared backend, tag invalidation, or to reuse one cache across functions.

TYPE: TTLCache | None DEFAULT: None

ttl

TTL in seconds for the private process-local cache.

Only valid when cache is omitted. It builds a private TTLCache(maxsize=maxsize, ttl=ttl) on a MemoryCacheAdapter for plain in-process memoization (the functools.lru_cache case). To share results across replicas, pass a TTLCache instead. Passing both cache and ttl raises TypeError.

TYPE: float | None DEFAULT: None

maxsize

Maximum number of entries in the private process-local cache. 0 (the default) means unlimited. Only used when cache is omitted and ttl is given.

TYPE: int DEFAULT: 0

key

Cache key template rendered from the call's arguments, so key="user:{user_id}" keys the entry under user:42 for a call with user_id=42. A literal template with no placeholders keys every call under the same string. Use it instead of the default argument-repr key when you want a stable, readable key. A key template fully determines the key, so typed does not apply. Passing both key and key_maker raises TypeError.

TYPE: str | None DEFAULT: None

key_maker

Optional custom key generation function. Receives (func, args, kwargs) and must return a string key. Use it for the fully dynamic case. For a simple template, pass key= instead. Passing both key and key_maker raises TypeError.

TYPE: Callable[[Callable[..., Any], tuple[Any, ...], dict[str, Any]], str] | None DEFAULT: None

skip

Optional predicate receiving the function result. When it returns True the result is not cached.

TYPE: Callable[[Any], bool] | None DEFAULT: None

typed

If True, arguments of different types are cached separately (e.g. 3 vs 3.0).

TYPE: bool DEFAULT: False

lock

Protect against duplicate work when many callers miss the same key at once (the "dog-pile" effect).

  • "local" (default): fold concurrent misses within the worker through an in-process lock, with no backend round-trip on a cold miss. Per-replica recompute is still possible.
  • True: fold concurrent misses to one execution. When the active Grelmicro app has a lock backend, misses fold across replicas through it. Otherwise an in-process lock folds them within the worker. An in-process lock is always applied first, so the backend is hit once per cold miss.
  • False: no protection. Every concurrent miss runs the function.

TYPE: bool | Literal['local'] DEFAULT: 'local'

early

Probabilistic early refresh (XFetch). A float in [0, 1). When a cached entry is read inside the last early fraction of its TTL, the call may roll a die and, on success, schedule a background recompute while still returning the cached value. The hottest keys then refresh before they expire, so no caller ever blocks on a cold miss.

Costs one extra recompute per refresh. Leave None to disable.

TYPE: float | None DEFAULT: None

stale_ttl

Serve-stale-on-error budget in seconds. When set, each cached result is also kept as a fallback copy for ttl + stale_ttl seconds. If a later recompute (on a miss) raises, the most recent value is served instead of propagating the error, for up to stale_ttl seconds past its TTL. A flaky upstream then degrades to slightly stale data instead of an error storm.

Composes with lock and early. Leave None to propagate errors as usual.

TYPE: float | None DEFAULT: None

tags

Tags to associate with each cached result. Each tag is a template rendered from the call's arguments, so tags=["users", "user:{user_id}"] tags the entry with both users and user:42 for a call with user_id=42. Literal tags with no placeholders pass through unchanged. Invalidate every entry sharing a tag at once with cache.delete_tags(...).

TYPE: Sequence[str] DEFAULT: ()

RAISES DESCRIPTION
TypeError

If both cache and ttl are given, if neither is given, or if both key and key_maker are given.

ValueError

If lock is not True, False, or "local", if early is outside [0, 1), or if stale_ttl is not positive.

RETURNS DESCRIPTION
Callable[[Callable[P, R]], Callable[P, R]]

A decorator that caches function results.

grelmicro.cache.memory

Memory Cache Adapter.

MemoryCacheAdapter

MemoryCacheAdapter()

Bases: CacheBackend

In-memory cache backend.

Stores entries in a Python dict with lazy TTL expiry. Suitable for testing and single-process applications.

Tag membership is tracked with two dicts kept in sync: a forward map from tag to its set of keys, and a reverse map from key to its set of tags. The reverse map lets a delete or a lazy expiry remove the key from every tag it belonged to, so no tag ever points at a key that is gone.

Initialize the memory cache backend.

get async

get(*, key: str) -> bytes | None

Get raw bytes by key.

Returns None if the key is missing or expired. Expired entries are removed lazily on access.

set async

set(
    *,
    key: str,
    value: bytes,
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store raw bytes with a TTL in seconds and optional tags.

get_many async

get_many(*, keys: Sequence[str]) -> dict[str, bytes]

Get raw bytes for many keys, returning only found entries.

set_many async

set_many(
    *,
    items: Mapping[str, bytes],
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store many keys with one TTL and optional tags.

delete async

delete(*, key: str) -> None

Delete a key and clean its tag membership (no-op if absent).

delete_many async

delete_many(*, keys: Sequence[str]) -> None

Delete many keys and clean their tag membership.

delete_tags async

delete_tags(*, tags: Sequence[str]) -> None

Delete every key associated with any of the given tags.

clear async

clear() -> None

Remove all entries.

grelmicro.cache.redis

Redis Cache Adapter.

RedisCacheAdapter

RedisCacheAdapter(
    *,
    provider: RedisProvider | None = None,
    env_prefix: str = "REDIS_",
    prefix: str = "",
)

Bases: CacheBackend

Redis cache storage backend.

Wraps a RedisProvider and implements the cache protocol: get, set (with per-entry TTL via SET ... PX), delete, batch operations, tag-based invalidation, and a prefix-scoped clear. Pass an explicit provider= to share a pool with other components, or rely on the default env_prefix= to build one from environment variables.

Each tag holds the fully qualified keys tagged with it. A reverse record next to each value lists the value's tags and self-expires with the value, so an expired key never leaves a stale tag entry behind. Both live under the cache prefix, so clear sweeps them too.

Initialize the Redis cache backend.

PARAMETER DESCRIPTION
provider

A pre-built RedisProvider. When set, the adapter borrows the provider's client and does not manage its lifecycle.

TYPE: RedisProvider | None DEFAULT: None

env_prefix

Environment variable prefix used by the implicit RedisProvider when provider is not set. Defaults to REDIS_. Use a custom prefix to split pools.

TYPE: str DEFAULT: 'REDIS_'

prefix

Prefix prepended to every Redis key (cache namespace).

TYPE: str DEFAULT: ''

provider property

provider: RedisProvider

The bound RedisProvider.

get async

get(*, key: str) -> bytes | None

Get raw bytes by key.

Returns None if the key is missing or expired.

set async

set(
    *,
    key: str,
    value: bytes,
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store raw bytes with a TTL in seconds and optional tags.

get_many async

get_many(*, keys: Sequence[str]) -> dict[str, bytes]

Get raw bytes for many keys, returning only found entries.

set_many async

set_many(
    *,
    items: Mapping[str, bytes],
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store many keys with one TTL and optional tags.

delete async

delete(*, key: str) -> None

Delete a key and clean its tag membership (no-op if absent).

delete_many async

delete_many(*, keys: Sequence[str]) -> None

Delete many keys and clean their tag membership.

delete_tags async

delete_tags(*, tags: Sequence[str]) -> None

Delete every key associated with any of the given tags.

clear async

clear() -> None

Remove all entries matching the configured prefix.

Uses SCAN to iterate keys without blocking Redis, then deletes in batches. Tag and reverse-tag sets live under the same prefix, so this sweeps them too.

grelmicro.cache.postgres

Postgres Cache Adapter.

PostgresCacheAdapter

PostgresCacheAdapter(
    *,
    provider: PostgresProvider | None = None,
    env_prefix: str = "POSTGRES_",
    prefix: str = "",
    table_name: str = "grelmicro_cache",
    auto_migrate: bool = True,
    cleanup_interval: float | None = None,
)

Bases: CacheBackend

Postgres cache storage backend.

Wraps a PostgresProvider and implements the cache protocol: get, set (with per-entry TTL via expires_at), delete, batch operations, tag-based invalidation, and a prefix-scoped clear. Entries live in a single table keyed on key with value BYTEA and expires_at TIMESTAMPTZ.

Tags live in a companion table that maps each key to its tags. A foreign key with ON DELETE CASCADE removes a key's tag rows whenever the key row goes away, so deleting by tag, by key, or by janitor never leaves an orphan tag row behind.

Pass an explicit provider= to share a pool with other components, or rely on the default env_prefix= to build one from environment variables.

Set cleanup_interval= to enable a background janitor that deletes expired rows. Off by default. Lazy expiry on get keeps reads correct, the janitor only reclaims storage.

Example:

from grelmicro.cache import Cache
from grelmicro.providers.postgres import PostgresProvider

postgres = PostgresProvider("postgresql://localhost:5432/app")
cache = Cache(postgres)

Read more in the Cache docs.

Initialize the Postgres cache backend.

PARAMETER DESCRIPTION
provider

A pre-built PostgresProvider. When set, the adapter borrows the provider's pool and does not manage its lifecycle.

TYPE: PostgresProvider | None DEFAULT: None

env_prefix

Environment variable prefix used by the implicit PostgresProvider when provider is not set. Defaults to POSTGRES_. Use a custom prefix to split pools.

TYPE: str DEFAULT: 'POSTGRES_'

prefix

Prefix prepended to every key (cache namespace).

TYPE: str DEFAULT: ''

table_name

Table that stores cache entries. Auto-created on first connect (set auto_migrate=False to opt out).

TYPE: str DEFAULT: 'grelmicro_cache'

auto_migrate

When True (the default), the adapter creates the table on __aenter__. Set to False when the schema is managed by your own migration tool.

TYPE: bool DEFAULT: True

cleanup_interval

Period in seconds between janitor runs that delete rows expired for more than one hour. Default None disables the janitor: lazy expiry on get still works, only storage reclamation is skipped.

TYPE: float | None DEFAULT: None

provider property

provider: PostgresProvider

The bound PostgresProvider.

get async

get(*, key: str) -> bytes | None

Get raw bytes by key.

Returns None if the key is missing or expired.

set async

set(
    *,
    key: str,
    value: bytes,
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store raw bytes with a TTL in seconds and optional tags.

The value upsert and the tag rows commit in one transaction.

get_many async

get_many(*, keys: Sequence[str]) -> dict[str, bytes]

Get raw bytes for many keys, returning only found entries.

set_many async

set_many(
    *,
    items: Mapping[str, bytes],
    ttl: float,
    tags: Sequence[str] = (),
) -> None

Store many keys with one TTL and optional tags.

Every value upsert and its tag rows commit in one transaction.

delete async

delete(*, key: str) -> None

Delete a key (no-op if absent).

The cascade removes the key's tag rows.

delete_many async

delete_many(*, keys: Sequence[str]) -> None

Delete many keys. The cascade removes their tag rows.

delete_tags async

delete_tags(*, tags: Sequence[str]) -> None

Delete every key associated with any of the given tags.

One statement deletes the matching value rows, and the cascade cleans their tag rows.

clear async

clear() -> None

Remove all entries matching the configured prefix.

Falls back to a full table delete when no prefix is set. The cascade cleans the matching tag rows.