feat(cache-manager): add add() for atomic store-if-absent of application values - #93
Merged
Merged
Conversation
…ion values CacheManager.add(key, value, ttl=None) -> bool stores a JSON value only when the key is free and reports whether it did. It runs on the backend's set_if_absent, so of several concurrent callers exactly one wins, which makes once-per-key work (webhook or email deduplication) race-free. set() and add() now share one _encode() helper for the JSON entry. Closes #65
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #65.
Change
CacheManager.add(key, value, ttl=None) -> boolstores a JSON value only when the key is free and returns whether it did.default_ttlhandling asset(). A non-JSON-serializable value raisesTypeError.backend.set_if_absent(Add an atomic set-if-absent (SET NX EX) to BaseCacheBackend for lock / slot acquisition #62), so the check and the write are one atomic operation on Memory, Redis and Memcached. Of several concurrent callers, exactly one getsTrue.add()returnsFalsefor it, even thoughget()andget_or_set()treat it as a miss. The docstring and the guide both say so.set()andadd()now share a private_encode()helper that builds the JSONCacheEntry.Docs:
docs/APP_CACHE.mdhas an example and a behavior bullet, and the Memcached note now listsadd().add().CLAUDE.mdis updated.[Unreleased]inCHANGELOG.mdhas an Added entry.Tests
The new tests in
tests/test_cache_manager.pyrun against Memory, and against Redis when a test server is configured:add()calls: exactly one succeeds, and the stored value is the winner's.ttlapplies, and the key can be added again after it lapses.default_ttlis used when nottlis given.TypeErroris raised and the key is left free.Local results:
manager.py.ruff,mypy --strictandzensical build --strictare clean.