From 0ef4dfd23051bd1cc8f06bccfcba05e2fdc8881b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Tue, 4 Nov 2025 15:47:15 +0100 Subject: [PATCH] DB cache bootstrapper: setConnection() instead of purge() (#1408) By purging stores, we "detach" existing cache stores from the CacheManager, making them impossible to adjust in the future. We also unnecessarily recreate them on every tenancy bootstrap/revert. A simpler case where this causes problems is defining a RateLimiter in a service provider. That injects a single cache store into the rate limiter singleton, which then becomes a completely independent object after tenancy is initialized due to the purge. This in turn means the central and tenant contexts share the rate limiter cache instead of using separate caches as one would expect. --- .../DatabaseCacheBootstrapper.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Bootstrappers/DatabaseCacheBootstrapper.php b/src/Bootstrappers/DatabaseCacheBootstrapper.php index ae547471..0e41849f 100644 --- a/src/Bootstrappers/DatabaseCacheBootstrapper.php +++ b/src/Bootstrappers/DatabaseCacheBootstrapper.php @@ -63,13 +63,17 @@ class DatabaseCacheBootstrapper implements TenancyBootstrapper $stores = $this->scopedStoreNames(); foreach ($stores as $storeName) { - $this->originalConnections[$storeName] = $this->config->get("cache.stores.{$storeName}.connection"); - $this->originalLockConnections[$storeName] = $this->config->get("cache.stores.{$storeName}.lock_connection"); + $this->originalConnections[$storeName] = $this->config->get("cache.stores.{$storeName}.connection") ?? config('tenancy.database.central_connection'); + $this->originalLockConnections[$storeName] = $this->config->get("cache.stores.{$storeName}.lock_connection") ?? config('tenancy.database.central_connection'); $this->config->set("cache.stores.{$storeName}.connection", 'tenant'); $this->config->set("cache.stores.{$storeName}.lock_connection", 'tenant'); - $this->cache->purge($storeName); + /** @var DatabaseStore $store */ + $store = $this->cache->store($storeName)->getStore(); + + $store->setConnection(DB::connection('tenant')); + $store->setLockConnection(DB::connection('tenant')); } if (static::$adjustGlobalCacheManager) { @@ -78,8 +82,8 @@ class DatabaseCacheBootstrapper implements TenancyBootstrapper // *from here* being executed repeatedly in a loop on reinitialization. For that reason we do not do that // (this is our only use of $adjustCacheManagerUsing anyway) but ideally at some point we'd have a better solution. $originalConnections = array_combine($stores, array_map(fn (string $storeName) => [ - 'connection' => $this->originalConnections[$storeName] ?? config('tenancy.database.central_connection'), - 'lockConnection' => $this->originalLockConnections[$storeName] ?? config('tenancy.database.central_connection'), + 'connection' => $this->originalConnections[$storeName], + 'lockConnection' => $this->originalLockConnections[$storeName], ], $stores)); TenancyServiceProvider::$adjustCacheManagerUsing = static function (CacheManager $manager) use ($originalConnections) { @@ -100,7 +104,11 @@ class DatabaseCacheBootstrapper implements TenancyBootstrapper $this->config->set("cache.stores.{$storeName}.connection", $originalConnection); $this->config->set("cache.stores.{$storeName}.lock_connection", $this->originalLockConnections[$storeName]); - $this->cache->purge($storeName); + /** @var DatabaseStore $store */ + $store = $this->cache->store($storeName)->getStore(); + + $store->setConnection(DB::connection($this->originalConnections[$storeName])); + $store->setLockConnection(DB::connection($this->originalLockConnections[$storeName])); } TenancyServiceProvider::$adjustCacheManagerUsing = null;