mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-15 06:44:03 +00:00
Refactor DatabaseCacheBootstrapper
This commit is contained in:
parent
54a2d8a693
commit
8b9b913c88
1 changed files with 48 additions and 39 deletions
|
|
@ -19,21 +19,34 @@ use Stancl\Tenancy\TenancyServiceProvider;
|
||||||
*
|
*
|
||||||
* Can be used instead of CacheTenancyBootstrapper.
|
* Can be used instead of CacheTenancyBootstrapper.
|
||||||
*
|
*
|
||||||
* On bootstrap(), all database cache stores' connections are set to 'tenant'
|
* By default, this bootstrapper scopes ALL cache stores that use the database driver. If you only
|
||||||
* and the database cache stores are purged from the CacheManager's resolved stores.
|
* want to scope SOME stores, set the static $stores property to an array of names of the stores
|
||||||
* This forces the manager to resolve new instances of the database stores created with the 'tenant' DB connection on the next cache operation.
|
* you want to scope. These stores must use 'database' as their driver.
|
||||||
*
|
*
|
||||||
* On revert(), the cache stores' connections are reverted to the originally used ones (usually 'central'), and again,
|
* Notably, this bootstrapper sets TenancyServiceProvider::$adjustCacheManagerUsing to a callback
|
||||||
* the database cache stores are purged from the CacheManager's resolved stores so that the originally used ones are resolved on the next cache operation.
|
* that ensures all affected stores still use the central connection when accessed via global cache
|
||||||
|
* (typicaly the GlobalCache facade or global_cache() helper).
|
||||||
*/
|
*/
|
||||||
class DatabaseCacheBootstrapper implements TenancyBootstrapper
|
class DatabaseCacheBootstrapper implements TenancyBootstrapper
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Cache stores to process. If null, all stores with 'database' driver will be processed.
|
* Cache stores to scope.
|
||||||
* If array, only the specified stores will be processed (with driver validation).
|
*
|
||||||
|
* If null, all cache stores that use the database driver will be scoped.
|
||||||
|
* If an array, only the specified stores will be scoped. These all must use the database driver.
|
||||||
*/
|
*/
|
||||||
public static array|null $stores = null;
|
public static array|null $stores = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should scoped stores be adjusted on the global cache manager to use the central connection.
|
||||||
|
*
|
||||||
|
* You may want to set this to false if you don't use the built-in global cache and instead provide
|
||||||
|
* a list of stores to scope (static::$stores), with your own global store excluded that you then
|
||||||
|
* use manually. But in such a scenario you likely wouldn't be using global cache at all which means
|
||||||
|
* the callbacks for adjusting it wouldn't be executed in the first place.
|
||||||
|
*/
|
||||||
|
public static bool $adjustGlobalCacheManager = true;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Repository $config,
|
protected Repository $config,
|
||||||
protected CacheManager $cache,
|
protected CacheManager $cache,
|
||||||
|
|
@ -47,7 +60,7 @@ class DatabaseCacheBootstrapper implements TenancyBootstrapper
|
||||||
throw new Exception('DatabaseCacheBootstrapper must run after DatabaseTenancyBootstrapper.');
|
throw new Exception('DatabaseCacheBootstrapper must run after DatabaseTenancyBootstrapper.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$stores = $this->getDatabaseCacheStores();
|
$stores = $this->scopedStoreNames();
|
||||||
|
|
||||||
foreach ($stores as $storeName) {
|
foreach ($stores as $storeName) {
|
||||||
$this->originalConnections[$storeName] = $this->config->get("cache.stores.{$storeName}.connection");
|
$this->originalConnections[$storeName] = $this->config->get("cache.stores.{$storeName}.connection");
|
||||||
|
|
@ -59,24 +72,26 @@ class DatabaseCacheBootstrapper implements TenancyBootstrapper
|
||||||
$this->cache->purge($storeName);
|
$this->cache->purge($storeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferably we'd try to respect the original value of this static property -- store it in a variable,
|
if (static::$adjustGlobalCacheManager) {
|
||||||
// pull it into the closure, and execute it there. But such a naive approach would lead to existing callbacks
|
// Preferably we'd try to respect the original value of this static property -- store it in a variable,
|
||||||
// *from here* being executed repeatedly in a loop on reinitialization. For that reason we do not do that
|
// pull it into the closure, and execute it there. But such a naive approach would lead to existing callbacks
|
||||||
// (this is our only use of $adjustCacheManagerUsing anyway) but ideally at some point we'd have a better solution.
|
// *from here* being executed repeatedly in a loop on reinitialization. For that reason we do not do that
|
||||||
$originalConnections = array_combine($stores, array_map(fn (string $storeName) => [
|
// (this is our only use of $adjustCacheManagerUsing anyway) but ideally at some point we'd have a better solution.
|
||||||
'connection' => $this->originalConnections[$storeName] ?? config('tenancy.database.central_connection'),
|
$originalConnections = array_combine($stores, array_map(fn (string $storeName) => [
|
||||||
'lockConnection' => $this->originalLockConnections[$storeName] ?? config('tenancy.database.central_connection'),
|
'connection' => $this->originalConnections[$storeName] ?? config('tenancy.database.central_connection'),
|
||||||
], $stores));
|
'lockConnection' => $this->originalLockConnections[$storeName] ?? config('tenancy.database.central_connection'),
|
||||||
|
], $stores));
|
||||||
|
|
||||||
TenancyServiceProvider::$adjustCacheManagerUsing = static function (CacheManager $manager) use ($originalConnections) {
|
TenancyServiceProvider::$adjustCacheManagerUsing = static function (CacheManager $manager) use ($originalConnections) {
|
||||||
foreach ($originalConnections as $storeName => $connections) {
|
foreach ($originalConnections as $storeName => $connections) {
|
||||||
/** @var DatabaseStore $store */
|
/** @var DatabaseStore $store */
|
||||||
$store = $manager->store($storeName)->getStore();
|
$store = $manager->store($storeName)->getStore();
|
||||||
|
|
||||||
$store->setConnection(DB::connection($connections['connection']));
|
$store->setConnection(DB::connection($connections['connection']));
|
||||||
$store->setLockConnection(DB::connection($connections['lockConnection']));
|
$store->setLockConnection(DB::connection($connections['lockConnection']));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function revert(): void
|
public function revert(): void
|
||||||
|
|
@ -91,24 +106,18 @@ class DatabaseCacheBootstrapper implements TenancyBootstrapper
|
||||||
TenancyServiceProvider::$adjustCacheManagerUsing = null;
|
TenancyServiceProvider::$adjustCacheManagerUsing = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function scopedStoreNames(): array
|
||||||
* Get the names of cache stores that use the database driver.
|
|
||||||
*/
|
|
||||||
protected function getDatabaseCacheStores(): array
|
|
||||||
{
|
{
|
||||||
// Get all stores specified in the static $stores property.
|
return array_filter(
|
||||||
// If they don't have the database driver, ignore them.
|
static::$stores ?? array_keys($this->config->get('cache.stores', [])),
|
||||||
if (static::$stores !== null) {
|
function ($storeName) {
|
||||||
return array_filter(static::$stores, function ($storeName) {
|
|
||||||
$store = $this->config->get("cache.stores.{$storeName}");
|
$store = $this->config->get("cache.stores.{$storeName}");
|
||||||
|
|
||||||
return $store && ($store['driver'] ?? null) === 'database';
|
if (! $store) return false;
|
||||||
});
|
if (! isset($store['driver'])) return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Get all stores with database driver if $stores is null
|
return $store['driver'] === 'database';
|
||||||
return array_keys(array_filter($this->config->get('cache.stores', []), function ($store) {
|
}
|
||||||
return ($store['driver'] ?? null) === 'database';
|
);
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue