Reverse-specification of oslo.cache — branch stable/2026.2
Branch
stable/2026.2@fc96999a99e4(4.3.0+ 3 commits) — repository https://opendev.org/openstack/oslo.cache — analysed on 2026-10-28
- Scope: all non-test code (9 modules, about 2,000 lines): region configuration, memoization, the pooled memcached backend, the dictionary and etcd3gw backends, the test proxy.
- References are
file:linerelative to the repository root;keystone:andkeystonemiddleware:point to those repositories (stable/2026.2). [inferred] marks a statement that was not followed to the end in the code.
Files of this specification
| File | Content |
|---|---|
| 01-library-interface_stable-2026.2.md | public API, [cache] → backend arguments, memcache pool, memoization (key, TTL, switch), options |
| 02-errors_stable-2026.2.md | ConfigurationError (8 situations, 2 defects), QueueEmpty, failures that are silent |
| 03-interactions_stable-2026.2.md | keys (SHA-1), values (pickled CachedValue), commands, lifetimes, server choice |
| 04-scenarios_stable-2026.2.md | 4 diagrams: memoized call, expiration, invalidation, failures |
| 05-async-processing_stable-2026.2.md | none |
| 06-change-history_stable-2026.2.md | 1 typing fix, 2 maintenance commits |
| 07-cache-contract_stable-2026.2.md | cache contract for Go services: requirements K/V/T/C, 19 scenarios recorded against fake memcached and Redis (19/19), recommendation |
Overview
oslo.cache turns the [cache] section of an OpenStack service into a dogpile.cache region:
- it chooses the backend (null by default, memcached, Redis, etcd…);
- it hashes every key with SHA-1;
- it gives services a memoization decorator, switched and timed per configuration group.
Values are pickled dogpile CachedValues (payload, {ct, v}). Their lifetime is checked by the reader from ct, not by memcached.
Key figures
5 public names; 37 options; 13 backends accepted; 2 exceptions; 0 background processing; 68 commands recorded.
Points of attention
- Expiration is client-side: memcached items have no TTL unless
backend_expiration_timeis set. Each reader applies its ownexpiration_time/cache_timeto the writer'sct, which assumes synchronised clocks (scenarios 5–7). - **
region.invalidate()is local to the process**: other processes keep serving the old value. Onlydelete, or Keystone's region id, invalidates for everyone (scenario 10). - Values are pickles: anyone who can write to memcached can run code in every service that reads it. Keep memcached private.
- Failure handling depends on the client library: memcached down = silent miss with python-memcached, but an exception with pymemcache (without the retry client) and Redis. A saturated pool raises
QueueEmptyafter 10 s (scenarios 14–16). - Mixing pymemcache and python-memcached across several servers sends the same key to different servers (03 § 4).
- Two defects: TLS refused for
dogpile.cache.bmemcached(typobmemcache), and an unformatted error message forbackend_expiration_time(02 § 1). - keystonemiddleware imports private modules (
_memcache_pool,_bmemcache_pool).
Source: reverse-spec-oslo.cache/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.