Release Notes¶
3.1.0¶
Features & Enhancements¶
Resource Pools:¶
- New
pool()class for managing concurrent execution slots withmax_sizelimit. - Use as context manager:
async with pool(key='worker-pool', max_size=10) - Use as decorator via
@pooled(key='...', max_size=N, on_full=callback) on_fullcallback receives same*args, **kwargsas wrapped function, enabling rescheduling, logging, or fallback logic.raise_on_full=Trueoption to raiseCachifyPoolFullErrorinstead of calling on_full.slot_expparameter for slot TTL (defaults todefault_pool_slot_expirationfrominit_cachify(), default 600 seconds).size()andasize()methods to check current pool occupancy.- New
CachifyPoolFullErrorexception exported frompy_cachify.
Configurable lock polling interval:¶
init_cachifynow accepts alock_poll_intervalparameter (default:0.1seconds).- This controls how frequently the library polls for lock availability when
nowait=False. - Lower values make lock acquisition more responsive but increase load on the cache backend.
- Higher values reduce backend load but may increase wait times.
Thread-safe async memory cache:¶
- The in-memory async cache wrapper (
AsyncWrapper) now uses anasyncio.Lockto protect concurrent access. - This prevents race conditions when multiple async tasks access the same in-memory cache simultaneously.
Improvements¶
- Minor code cleanup in
MemoryCache.delete()for better efficiency.
3.0.0¶
In short, 3.0.0 focuses on:
- Instance-based usage (
Cachify) and multiple independent caches per app. - Stronger locking semantics backed by atomic
nxsupport in cache clients. - A configurable
default_cache_ttlwith clearer TTL precedence rules. - Cleanup of long-deprecated aliases and stricter type checking on modern Python versions.
- Documentation updates and improvements, including a separate page to use with Agentic systems and LLMs.
Features & Enhancements¶
Multiple cachify instances per app:¶
init_cachifynow supportsis_global: bool = Trueand returns aCachifyinstance.- When
is_global=True(default),init_cachifyconfigures the global client used by top-levelcached,lock, andonceand returns aCachifyinstance backed by that client. - When
is_global=False,init_cachifydoes not modify the global client and instead returns an independentCachifyinstance exposing:Cachify.cached(...)Cachify.lock(...)Cachify.once(...)
New public Cachify type:¶
Cachifyis now publicly exported frompy_cachify.- It provides a convenient, instance-scoped API over the same high-level decorators:
@Cachify.cached(...)@Cachify.lock(...)@Cachify.once(...)
- All instance methods share the same semantics as the corresponding top-level decorators, but are bound to a specific client/prefix.
Improved reset and lock-query semantics in helpers:¶
- The helper functions
reset,a_reset,is_locked, andis_alockedhave been reworked to:- Accept internal parameters (
_pyc_key,_pyc_signature,_pyc_operation_postfix,_pyc_original_func,_pyc_client_provider) to make them fully aware of which client and which wrapped function they are operating on and prevent collisions with user defined functions args and kwargs.
- Accept internal parameters (
Configurable default cache TTL:¶
init_cachifyandCachifynow accept an optionaldefault_cache_ttlparameter.- If a
@cacheddecorator does not specifyttl, thedefault_cache_ttlof the underlying client is used as the fallback. - Passing
ttl=Noneto@cachednow explicitly means “no expiration”, even ifdefault_cache_ttlis set. - Effective TTL precedence:
- If
@cached(ttl=...)is provided, that value is used. - Else, if the client has
default_cache_ttlset, that value is used. - Else, entries are stored without expiration.
- If
Stronger lock correctness with atomic nx support:¶
- Lock acquisition and the
oncedecorator now rely on an atomic “set-if-not-exists” (nx) operation provided by the underlying cache client. - Built-in clients (in-memory, Redis examples) have been updated to implement
set(..., nx=True)semantics for lock keys. - This significantly reduces race conditions in concurrent environments and makes lock behavior more predictable.
Multi-layer caching support:¶
- Thanks to the helper changes and the instance-scoped API, it is now straightforward to stack multiple
cacheddecorators, for example:- A global cache with a long TTL; and
- A local instance cache with a shorter TTL on top of it.
- Calling
reset(*args, **kwargs)on the outermost wrapper will:- Clear that wrapper’s cache entry; and
- Attempt to call
reseton the inner wrapper(s), if they expose such a method, so the entire “stack” is reset for the given arguments.
- This pattern is documented in the updated
cachedreference and tutorial.
Stricter typing and tooling:¶
- Python baseline bumped to 3.9+.
- Core types updated to use
collections.abc.Awaitableand built-in generics (dict[...],tuple[...], etc.). typing-extensionsdependency bumped (>=4.15.0) andbasedpyrightconfiguration added for strict type checking on thepy_cachifypackage.
Breaking Changes¶
Deprecated aliases removed:¶
- The following deprecated functions, announced in 2.0.0 as scheduled for removal in 3.0.0, have now been removed:
async_cachedsync_cachedasync_oncesync_once
- Use the unified decorators instead:
cachedfor both sync and async caching.oncefor both sync and async “once at a time” locking.
Python 3.8 support dropped:¶
- The supported Python versions are now 3.9–3.14.
- Python 3.8 is no longer supported and is removed from classifiers and test matrix.
Notes on Migration from 2.x to 3.0.0¶
If you implemented (used) a custom cache client:¶
- Ensure your client supports an atomic "set-if-not-exists" semantics used by locks and
once. - Concretely, the client should implement a
set(key, value, ttl=None, nx=False)(or equivalent) method where:nx=Falsebehaves like a normal set; andnx=Trueonly sets the value if the key does not already exist, returning an appropriate success indicator.
- Without
nxsemantics, lock andoncebehavior may no longer be correct in 3.0.0.
If you only used:¶
init_cachify(...),cached,lock,once, and did not use any of the deprecated aliases or internal APIs, you should be able to upgrade with no code changes.
If you used any of the deprecated aliases:¶
- Replace:
sync_cached/async_cachedwithcached(it works for both sync and async).sync_once/async_oncewithonce.
2.0.10¶
Features & Enchancements¶
- Default log level is now DEBUG
- Dependencies bump
2.0.9¶
Features & Enchancements¶
- Better error message on the mismatch of key format params and function arguments
Bugfixes¶
- Fix default arguments are not respected when crafting cache key
2.0.7¶
Features & Enchancements¶
- Bump dependencies
- Add Python 3.13 Support
2.0.4¶
Features & Enchancements¶
- Bump dependencies
- Better README and Docs
2.0.0¶
Features & Enchancements¶
-
Lock improvements: Locks are now way more versatile and support new parameters like:
- Whether to wait for the lock to expire or not (
nowait, boolean) - Timeouts for how long should it try to acquire a lock. (
timeout, int | float | None) - Expiration param to prevent deadlocks (
exp, int | None) -
When using lock as a decorator or using
oncedecorator two methods are being added to the wrapped function:is_locked(*args, **kwargs)- to check whether the lock is acquired or notrelease(*args, **kwargs)- to forcefully release a lock.
-
More info could be found here.
- Whether to wait for the lock to expire or not (
-
File layout improved: All internal files have been made private helping LSP's and IDE's provide better import locations for the features py-cachify provides.
-
Type annotations now feature TypeIs & Protocols: Updated type annotations now provide even better IDE support, making it easier to write better code. They expose all methods attached to decorated functions and help you inline.
-
Additional tests were added
-
cacheddecorator improvements: There is now a new method attached to the wrapped functions calledreset(*args, **kwargs)to allow for a quick cache resets.- More info can be found here.
-
Bump dependencies
Breaking Changes¶
- async_lock: Async lock has been removed, you should replace it with
locksince it now can work in both contexts. - import locations: since files were renamed and moved around quite a bit, some import locations may not work after the 2.0.0 release, so I recommend reimporting used functions to ensure they work in your project.
Deprecations¶
- async_once, sync_once, async_cached, sync_cached: These are now deprecated and scheduled for removal in 3.0.0
(all of those methods are just aliases for
cachedandonce).
Miscellaneous¶
- Documentation: Documentation was refactored and greatly improved.
I recommend checking out full API reference to get familiar with changes and new features.
1.1.2¶
Features & Enchancements¶
- Bump dependencies
- Docs update to include info on
init_cachifyprefixparameter
1.1.0¶
Features & Enchancements¶
- Custom encoders/decoders for the
cacheddecorator:enc_decparameter introduced on acacheddecorator.
Miscellaneous¶
- Documentation update