Skip to content

fix(cache-manager): return the round-tripped value from get_or_set on a miss - #313

Merged
allen0099 merged 1 commit into
masterfrom
fix/get-or-set-round-trip
Sep 27, 2026
Merged

allen0099 merged 1 commit into
masterfrom
fix/get-or-set-round-trip

Conversation

@allen0099

@allen0099 allen0099 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

CacheManager.get_or_set() returned the factory's object on a miss and the JSON-decoded copy on a hit:

miss: (1, 2)      hit: [1, 2]
miss: {1: 'a'}    hit: {'1': 'a'}

A miss now encodes the value once with the same _encode() that set() uses, stores those bytes, and returns json.loads of the same bytes. It does not serialise twice, and both paths give the same result.

  • The contract is otherwise unchanged. A backend set error still propagates, as it did through self.set(). There is no fail-open path in CacheManager.
  • A non-JSON-serialisable value (datetime, Decimal, UUID, a pydantic model) still raises TypeError after the factory has run, and nothing is stored. This can't be avoided, so it is now documented.
  • add() returns a bool, not the value, so it doesn't have this inconsistency. No other method returns the stored value.
  • Docs: a new "JSON round-trip" section in docs/APP_CACHE.md and its zh-TW mirror, with a table of how each type reads back.
  • Typed reads (CacheManager: typed reads, incr, and get_many/set_many #249) are out of scope.

Tests

  • tuple, int-keyed dict and nested values: the miss result equals the hit result, including its type. These run on memory and live Redis.
  • the value is encoded exactly once, and the stored bytes are that encoding.
  • a non-serialisable value raises TypeError, the factory runs once, and the key stays free.

Including the live Redis and Memcached tests: 1195 passed, 1 skipped, total coverage 99%, manager.py 100%.

Changelog

changelog.d/235.fixed.md

Closes #235

… a miss

On a miss get_or_set returned the factory's object as is, on a hit the
JSON-decoded copy, so a tuple came back as a tuple then a list and int
dict keys as ints then strings. Encode once, store those bytes and
return them decoded. Document the JSON round-trip rules.
@allen0099 allen0099 added this to the 0.3.9 milestone Sep 27, 2026
@allen0099
allen0099 merged commit d1c41e0 into master Sep 27, 2026
12 checks passed
@allen0099
allen0099 deleted the fix/get-or-set-round-trip branch September 27, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CacheManager.get_or_set returns a different value on a miss than on a hit

1 participant