feat: make the cache pool backend configurable with CACHE_ADAPTER#498
Merged
Conversation
The application cache pools (feeds, calendar, screen auth/status, interactive slides) were hard-wired to cache.adapter.redis, forcing every installation to run Redis. A pool's adapter must be a service id at container compile time, so the backend cannot be switched with a runtime %env()% placeholder; instead the pools now extend an abstract app.cache.adapter service backed by App\Cache\CacheAdapterFactory, which builds the adapter selected by the new CACHE_ADAPTER env var at runtime: redis (default, unchanged), memcached, dbal (shared via the application database, table auto-created), filesystem or apcu. The factory mirrors the built-in adapter wiring: lazy connections, pools cleared by cache:clear and reset in long-running workers. A schema_filter hides the dbal adapter's cache_items table from the Doctrine schema tools. Tests now run with CACHE_ADAPTER=filesystem instead of per-pool overrides, removing the implicit Redis dependency from the three previously unoverridden pools. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The itkdev/php8.4-fpm images ship ext-apcu disabled (apc.enabled=0); CACHE_ADAPTER=apcu needs PHP_APCU_ENABLED=1 and a suitable PHP_APCU_MEMORY_SIZE set on the container. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tuj
approved these changes
Jun 12, 2026
…e-adapter-env-config # Conflicts: # CHANGELOG.md
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.
Summary
The application cache pools (
feeds.cache,feed.without.expire.cache,calendar.api.cache,auth.screen.cache,screen.status.cache,interactive_slide.cache) were hard-wired tocache.adapter.redis, forcing every installation to run Redis. This PR makes the backend selectable at runtime with a newCACHE_ADAPTERenv var:redis(default, behavior unchanged),memcached,dbal,filesystemorapcu.Why a factory instead of
%env()%in cache.yamlSymfony resolves a pool's
adapter:option to a concrete service id at container compile time (CachePoolPassmakes each pool aChildDefinitionof the adapter service), so the choice cannot be expressed with a runtime env placeholder. The pools now extend an abstractapp.cache.adapterservice backed byApp\Cache\CacheAdapterFactory, which builds the selected adapter at runtime;CachePoolPassinjects each pool's computed namespace and configureddefault_lifetimeas the factory arguments. The custom parent mirrors the built-incache.adapter.*wiring: lazy Redis/Memcached connections, pools attached tocache.default_clearer(wiped bycache:clearon deploy, as before) andreset: resetfor long-running workers.Backend notes
REDIS_CACHE_DSN.MEMCACHED_CACHE_DSN, requires ext-memcached). Documented caveat: Memcached LRU-evicts under memory pressure, so long-lived entries (screen status, activation codes) can disappear early.cache_itemstable is auto-created on first write. Aschema_filterhides it fromdoctrine:migrations:diff/schema:validate. TTL is honored on read (expired rows are deleted when encountered).var/cache/<env>/pools; for single-server setups without Redis.All backends honor
default_lifetimeand per-item TTLs (PSR-6 contract); an unknownCACHE_ADAPTERvalue fails fast with a message listing the valid options.arraywas deliberately not offered: a per-request cache breaks the screen activation flow (auth.screen.cache).Files Changed
src/Cache/CacheAdapterFactory.php(new) — runtime adapter factoryconfig/services.yaml— factory wiring + abstractapp.cache.adapterparentconfig/packages/cache.yaml— pools now extendapp.cache.adapterconfig/packages/doctrine.yaml—schema_filterforcache_items.env—CACHE_ADAPTER+MEMCACHED_CACHE_DSNdocs and defaults.env.test+ deletedconfig/packages/test/cache.yaml— tests run withCACHE_ADAPTER=filesysteminstead of per-pool overrides, removing the implicit Redis dependency from the three pools the old override file didn't covertests/Cache/CacheAdapterFactoryTest.php(new) — unit tests incl. dbal roundtrip with table auto-creation (sqlite) and lazy redis/memcached creationCHANGELOG.md— Unreleased entryTest Plan
task test:api -- --filter CacheAdapterFactoryTest— 7 tests (APCu skipped where ext missing)task test:api -- --filter AuthenticationScreenTest— screen auth flow through factory-built filesystem pools: greendocker compose exec -e CACHE_ADAPTER=<redis|dbal|filesystem> phpfpm bin/console cache:pool:clear feeds.cacheall succeed;-e CACHE_ADAPTER=bogusfails withUnknown CACHE_ADAPTER "bogus". Expected one of: "redis", "memcached", "dbal", "filesystem", "apcu".task code-analysis,task rector:check,task coding-standards:check,scripts/check-env-coverage.sh— greensrc/Dto/src/Statetouched), so no spec regeneration needed🤖 Generated with Claude Code