InMemoryCacheAdapter — In-Memory Cache Backend
A CacheProviderInterface implementation for tests and single-process usage,
with no external Redis dependency. Locks are process-local.
InMemoryCacheAdapter
InMemoryCacheAdapter(
key_prefix: str = "test:", cache_name: str = "memory"
)
Bases: CacheProviderInterface
Thread-safe in-memory cache implementation.
This adapter provides a complete cache implementation using Python dictionaries with thread-safe operations.
Features
- Full CacheProviderInterface compliance
- Thread-safe operations
- TTL support with lazy expiration
- Mock distributed locks (single-process only)
Example
cache = InMemoryCacheAdapter() cache.set("key", {"data": "value"}, ttl=timedelta(minutes=5)) data = cache.get("key") with cache.get_lock("my_lock") as lock: ... # Critical section (only within single process!) ... pass
Warning
This is for TESTING ONLY. Data is not persisted and locks only work within a single process.
Initialize in-memory cache.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_prefix
|
str
|
Prefix for all cache keys |
'test:'
|
cache_name
|
str
|
Name for metrics identification |
'memory'
|
provider_name
property
provider_name: str
Return 'memory' as the provider identifier.
cleanup_expired
cleanup_expired() -> int
Lock-acquiring entry point for periodic expiration sweeps.
Wraps the unlocked _cleanup_expired() with self._lock so
external callers (CleanupService) can safely invoke it. self._lock
is a non-reentrant threading.Lock; reusing the private method from
a non-locked context would deadlock.
Returns:
| Type | Description |
|---|---|
int
|
Number of expired entries removed. |
clear_all_instances
classmethod
clear_all_instances() -> None
Clear the class-level weak registry (for test fixtures).
get
get(key: str) -> Any | None
Get value by key.
set
set(
key: str, value: Any, ttl: timedelta | None = None
) -> bool
Set value with optional TTL.
delete
delete(key: str) -> bool
Delete key from cache.
exists
exists(key: str) -> bool
Check if key exists in cache.
incr
incr(key: str, amount: int = 1) -> int
Atomically increment a counter.
decr
decr(key: str, amount: int = 1) -> int
Atomically decrement a counter.
expire
expire(key: str, ttl: timedelta) -> bool
Set expiration on existing key.
ttl
ttl(key: str) -> int | None
Get remaining TTL in seconds.
setnx
setnx(
key: str, value: Any, ttl: timedelta | None = None
) -> bool
Set value only if key does not exist.
cas_dict_field
cas_dict_field(
key: str,
field: str,
expected: Any,
new_value: dict[str, Any],
ttl: timedelta | None = None,
) -> bool
Atomic single-field CAS on a dict-valued record (lock-wrapped).
get_lock
get_lock(
name: str,
timeout: timedelta = timedelta(seconds=10),
blocking_timeout: float | None = None,
) -> DistributedLock
Get a distributed lock instance.
Resolves the registry key once via self._make_key(name) so
two adapter instances with different key_prefix map the same
user-facing name to distinct entries in the class-level
InMemoryLock._locks registry.
mget
mget(keys: list[str]) -> dict[str, Any]
Get multiple values at once.
mset
mset(
mapping: dict[str, Any], ttl: timedelta | None = None
) -> bool
Set multiple values at once.
mdelete
mdelete(keys: list[str]) -> int
Delete multiple keys at once.
push_limit
push_limit(
key: str,
value: Any,
max_len: int,
ttl: timedelta | None = None,
) -> int
Append value to a list and trim to max_len under thread lock.
list_range
list_range(key: str, start: int, end: int) -> list[Any]
Return elements from start to end (inclusive).
health_check
health_check() -> bool
Check if cache is healthy.
set_health_status
set_health_status(healthy: bool) -> None
Set health status for testing.
flush_all
flush_all() -> bool
Clear all keys.
keys
keys(pattern: str = '*') -> list[str]
Find keys matching a pattern.
scan
scan(
pattern: str = "*", count: int = 100
) -> tuple[int, list[str]]
Incrementally iterate keys matching a pattern.
get_store_size
get_store_size() -> int
Get number of entries in store (for testing).
clear_all
clear_all() -> None
Clear entire store including all prefixes (for testing cleanup).