Cache¶
xcoreSDK provides two decorators for transparent result caching: @cached to store handler results and @invalidate to evict stale entries.
Both decorators work with any cache service registered as "cache" in self.ctx.services. They no-op silently when the service is absent.
@cached¶
Caches the return value of an async action handler.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
ttl |
int \| None |
None |
Time-to-live in seconds; None = no expiry |
key |
callable \| str \| None |
None |
Cache key strategy (see below) |
Key strategies¶
Callable (recommended):
String — used as-is (static key, shared across all callers):
None — auto-generates a SHA-256 hash of (plugin_name, method_name, payload):
Behavior¶
- Compute cache key
cache.get(key)→ return cached value on hit- On miss: call the handler, store result with
cache.set(key, result, ttl=ttl) - Return result
If self.ctx is None or the "cache" service is not registered, the handler is called directly with no caching.
@invalidate¶
Evicts a cache entry after the handler executes. Used to keep caches consistent after mutations.
Parameters
| Name | Type | Description |
|---|---|---|
key |
callable \| str |
Same key strategies as @cached |
Eviction happens after the handler returns (success or failure). If the key does not exist, the operation is a no-op.
Combining @cached and @invalidate¶
A common pattern: cache reads, invalidate on writes:
Manual cache access¶
For cache operations not covered by the decorators:
Backend configuration¶
The cache backend is configured in the kernel, not in the plugin. Switching between in-memory and Redis requires no plugin code changes — the same @cached API works on both.
| Backend | Use case |
|---|---|
In-memory (dict) |
Development, single-process |
| Redis | Production, multi-process, distributed TTL |