From b532ef08fa4894b728b44000abcc9f7c3b232951 Mon Sep 17 00:00:00 2001 From: IanM Date: Fri, 6 Mar 2026 23:38:51 +0000 Subject: [PATCH] perf: add MemoryCacheSettingsRepository layer to settings chain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RedisCacheSettingsRepository::get() calls all() on every invocation, which calls cache->remember() on every call — a Redis GET each time. With ~60–100 settings reads per page request, each returning the 154 KB flarum:settings blob, this alone accounts for the majority of Redis egress bandwidth. Wrapping with MemoryCacheSettingsRepository restores the per-request in-process cache that Flarum core's SettingsServiceProvider provides by default. After the first settings read per request, all subsequent reads within the same request are local array lookups with zero network cost. Redis is hit at most once per request instead of once per settings->get() call. Co-Authored-By: Claude Sonnet 4.6 --- src/Provides/Settings.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Provides/Settings.php b/src/Provides/Settings.php index ab4a132..8f737d1 100644 --- a/src/Provides/Settings.php +++ b/src/Provides/Settings.php @@ -18,6 +18,7 @@ use Flarum\Foundation\Event\ClearingCache; use Flarum\Settings\DatabaseSettingsRepository; use Flarum\Settings\DefaultSettingsRepository; +use Flarum\Settings\MemoryCacheSettingsRepository; use Flarum\Settings\SettingsRepositoryInterface; use FoF\Redis\Configuration; use FoF\Redis\Overrides\RedisManager; @@ -59,16 +60,21 @@ public function __invoke(Configuration $configuration, Container $container) return new Repository($store); }); - // Replace the entire settings repository binding to use Redis caching instead of MemoryCache + // Replace the entire settings repository binding with a three-layer chain: + // MemoryCacheSettingsRepository — per-request in-process cache (zero network cost after first read) + // └── RedisCacheSettingsRepository — cross-request Redis cache (one Redis GET per request, 1h TTL) + // └── DatabaseSettingsRepository — source of truth (MySQL, hit only on Redis miss) $container->singleton(SettingsRepositoryInterface::class, function (Container $container) { $cache = $container->make('cache.settings'); return new DefaultSettingsRepository( - new RedisCacheSettingsRepository( - new DatabaseSettingsRepository( - $container->make(ConnectionInterface::class) - ), - $cache + new MemoryCacheSettingsRepository( + new RedisCacheSettingsRepository( + new DatabaseSettingsRepository( + $container->make(ConnectionInterface::class) + ), + $cache + ) ), $container->make('flarum.settings.default') );