🌀 Component Caching Utilities¶
Module: duck.html.components.utils.caching
This module provides a flexible, high-performance caching system for Duck HTML components.
It allows component instances to be reused across renders while preserving correctness, immutability, and thread safety.
Caching is especially useful for:
Expensive component initialization
Static or semi-static UI elements
Reducing render latency under load
Key Concepts¶
What Is Cached?¶
Component instances, not rendered HTML
Cached components may be frozen to enable fast re-rendering
Returned components are copied by default to avoid tree ownership conflicts
Threading Model¶
Cached components may trigger background tasks (load, pre-render, VDOM computation)
Background execution uses a shared component thread pool
Excessive background activity may increase latency — use caching thoughtfully
Default Cache Backend¶
DEFAULT_CACHE_BACKEND = InMemoryCache(maxkeys=2048)
Uses an in-memory LRU-style cache
Automatically evicts older entries when the limit is reached
Custom backends may be supplied
Exceptions¶
ComponentCachingError¶
Raised when:
Invalid cache configuration is provided
Target keys are missing
Cache key computation fails
Cache Key Generation¶
make_cache_key(...)¶
make_cache_key(
component_cls,
args,
kwargs,
namespace: Optional[str | Callable] = None
) -> Tuple
How keys are constructed:
Optional namespace prefix
Component class
Frozen positional arguments
Frozen keyword arguments
Namespaces allow bulk invalidation and logical grouping.
cached_component Decorator¶
@cached_component(...)
class MyComponent(Component):
...
This decorator enables component-level caching with fine-grained control.
Parameters¶
targets¶
Optional[List[str | Callable]]
Explicitly define what participates in caching.
Strings → keyword argument names
Callables → custom cache key extractors
Example:
targets=['id', lambda *a, **k: k['user'].id]
When
targetsis used:
Positional args are ignored
ignore_argsandignore_kwargsare invalid
cache_backend¶
Custom backend implementing:
get(key)set(key, value, expiry=None)
Defaults to InMemoryCache.
expiry¶
Optional[float]
Cache TTL in seconds.
namespace¶
Optional[str | Callable]
Adds a prefix to cache keys.
Useful for:
Versioning
Bulk invalidation
Feature grouping
ignore_args¶
Optional[List[int]]
Indices of positional arguments to exclude from the cache key.
ignore_kwargs¶
Optional[List[str]]
Keyword argument names to exclude from the cache key.
skip_cache_attr¶
str = 'skip_cache'
If a component instance has this attribute set to True, caching is skipped.
Useful for:
Debugging
One-off renders
on_cache_result¶
Optional[Callable]
Hook executed when a cached component is returned.
Typical use cases:
Reinitializing transient state
Rebinding event handlers
freeze¶
bool = False
If enabled:
Cached components are frozen
Enables fast, immutable re-rendering
Required for static components
return_copy¶
bool = True
Controls whether a copy of the cached component is returned.
Why this matters:
Prevents component tree ownership conflicts
Avoids
ComponentCopyErrorEnsures isolation between renders
Special rules:
Frozen
Pagecomponents are never copied
_no_caching¶
Internal flag used by higher-level decorators to disable caching.
Runtime Behavior¶
Cache Miss¶
Component is instantiated
Cached if allowed
Frozen if requested
Background tasks may be scheduled
Copy returned (if enabled)
Cache Hit¶
Cached component retrieved
_is_from_cacheflag setCopy returned (if enabled)
on_cache_resulthook executed
Background Optimization¶
When returning a copy:
The original cached component may perform:
load()pre_render()render()to_vdom
This ensures subsequent cache hits are faster.
Task execution strategy:
Loaded components → fine-grained tasks
Unloaded components → batched execution
Functional API¶
CachedComponent(...)¶
CachedComponent(component_cls: Type, **cache_options)
Creates a cached component factory without decorators.
Example¶
cached_btn = CachedComponent(
Button,
namespace='welcome-btn',
targets=['id', 'text'],
)
btn = cached_btn(id='btn-1', text='Hello')
btn.is_from_cache() # False on first call
Static Component Utilities¶
Module: duck.html.components.utils.static
This module builds on the caching system to define static (fully frozen) components.
Static components:
Are cached
Are frozen immediately
Are safe to reuse across requests
Offer maximal rendering performance
static_component Decorator¶
@static_component(...)
class MyStaticComponent(Component):
...
This is a specialized wrapper around cached_component with:
freeze=TrueOptional caching toggle
Simplified API
Parameters¶
use_caching¶
bool = True
Allows static freezing without caching when disabled.
cache_targets¶
Equivalent to targets in cached_component.
cache_backend¶
Custom cache backend.
cache_expiry¶
TTL for static cache entries.
cache_namespace¶
Namespace prefix for static components.
cache_ignore_args¶
Indices of positional arguments to ignore.
cache_ignore_kwargs¶
Keyword argument names to ignore.
skip_cache_attr¶
Attribute name used to skip caching.
on_cache_result¶
Hook executed on cache hits.
return_copy¶
Controls whether copies are returned.
Defaults to
TrueFrozen
Pagecomponents are still returned as-is
Example¶
@static_component()
class MyStaticButton(Button):
pass
btn = MyStaticButton(text='Hello')
btn.is_frozen() # True
btn.is_from_cache() # False
btn2 = MyStaticButton(text='Hello')
btn2.is_from_cache() # True
Functional API¶
StaticComponent(...)¶
StaticComponent(component_cls: Type, **static_options)
Creates a static component factory without decorators.
Example¶
static_btn = StaticComponent(
Button,
cache_targets=['id', 'text'],
)
btn = static_btn(id='btn', text='Hello')
btn.is_frozen() # True
btn.is_from_cache() # False initially
When to Use What¶
Use Case |
Recommended |
|---|---|
Expensive dynamic components |
|
Fully static UI elements |
|
Functional factories |
|
Maximum performance |
Static + freeze |
Summary¶
Caching operates at the component instance level
Copies ensure safety across render trees
Freezing enables near-zero-cost re-rendering
Static components are the fastest option
Background execution optimizes future cache hits
This system is designed to scale cleanly under high concurrency while preserving correctness and developer control.