loom.core.cache.decorators¶
Functions
|
Mark a coroutine whose result a bound |
|
Declarative marker for custom repository read methods. |
|
Declarative marker for repositories that support cache wrapping. |
|
Return the policy func was marked with by |
Return whether cls was marked with |
Classes
|
What a |
- loom.core.cache.decorators.cached(cls)[source]¶
Declarative marker for repositories that support cache wrapping.
- Parameters:
cls (T)
- Return type:
T
- loom.core.cache.decorators.declares_cache_policy(cls)[source]¶
Return whether cls was marked with
cached().
- loom.core.cache.decorators.cache_query(*, scope='list', ttl_key=None)[source]¶
Declarative marker for custom repository read methods.
Annotate the return type. The wrapper derives a codec from it and applies it to the cached read and to the fresh one alike, so a hit and a miss return the same type; the supported grammar is a
msgspec.Struct, a scalar, or alist,tupleor optional of those. A return type outside it — a mapping, a generic container,Any, a forward reference the defining module cannot resolve — emits aDeprecationWarningwhen the repository is wrapped, and keeps the old behaviour, where the cached call returns the decoded payload rather than the declared type.The declared type is what the caller gets, on the fresh call as on the cached one: a method annotated
-> Statsthat returns a subclass ofStatshands back a narrowedStats, and the fields the subclass added are dropped. Declare the type you mean to return.A method that returns
Noneis not cached: the backend cannot tell a storedNonefrom a miss, so the read runs again next time. A cached payload that no longer fits the declared type — an older deployment wrote it, and the type has since gained a field — is treated as a miss and overwritten, not raised to the caller.Treat the returned value as immutable. Concurrent callers that miss together are served the same object by the coalesced load, while a caller served from the cache gets a freshly decoded one, so mutating a result makes the two paths disagree. Return a struct, or a fresh copy.
scope="entity"requires the model’s primary key as the first positional argument (a keyword argument does not count); the wrapper raisesTypeErrorotherwise, before touching the cache backend. When the primary-key type resolves to a plain class the argument must be of that exact type — adatetimefor adatekey or aboolfor anintkey is rejected — while a key declaredint | Noneresolves no class and gets no call-time validation. A read keyed by any other field is a list-scoped read.- Parameters:
- Returns:
The decorator that marks the method.
- Return type:
Callable[[F], F]
- loom.core.cache.decorators.cache_call(*, ttl_key=None, unless=None, version=1)[source]¶
Mark a coroutine whose result a bound
CachedCallsmay store.The decorator only declares: it writes the policy on the function and returns the very same object, so the module imports with no configuration and the coroutine stays importable and unit-testable on its own. The composition root binds it later.
The coroutine must be a pure function of its arguments: it may not read ambient identity — a contextvar tenant, a caller’s credential — and may not hold a caller-scoped session. The key sees only the arguments, and the load is detached into its own task, so a coroutine that reads ambient state serves one caller’s answer to another.
A cached call is a TTL cache with no invalidation: unlike a repository read it carries no dependency tags, because loom cannot know what a coroutine depends on. It expires, or the caller bumps version.
- Parameters:
ttl_key (str | None) – Key whose
ttl:override applies. It shares the namespace with entity TTLs, so a key equal to an entity name deliberately shares that entity’s override.unless (Callable[[Any], bool] | None) – Predicate over the result; truthy means the result is returned and nothing is stored. An empty answer from a rate-limited service is the case it exists for.
version (int) – Bump to invalidate every entry this function already wrote.
- Returns:
The decorator that marks the coroutine.
- Raises:
TypeError – The decorated object is not a coroutine function. A cached call is awaited once and its single result is stored, which a plain function, a generator and an async generator cannot honour.
- Return type:
Callable[[F], F]
- loom.core.cache.decorators.declares_cache_call(func)[source]¶
Return the policy func was marked with by
cache_call().- Parameters:
func (object) – Any callable, marked or not.
- Returns:
The declared policy, or
Nonewhen func carries none.- Return type:
_CallPolicy | None