1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-13 10:44:03 +00:00

Update prefix bootstrapper and test (setStore() in CacheManager and Repository needed)

This commit is contained in:
lukinovec 2022-12-08 16:24:54 +01:00
parent 4c33df1aa5
commit 825a565fa2
2 changed files with 27 additions and 17 deletions

View file

@ -4,21 +4,20 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Bootstrappers; namespace Stancl\Tenancy\Bootstrappers;
use Illuminate\Cache\Repository as CacheRepository; use Illuminate\Cache\CacheManager;
use Illuminate\Contracts\Config\Repository; use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Stancl\Tenancy\Contracts\TenancyBootstrapper; use Stancl\Tenancy\Contracts\TenancyBootstrapper;
use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Contracts\Tenant;
class PrefixCacheTenancyBootstrapper implements TenancyBootstrapper class PrefixCacheTenancyBootstrapper implements TenancyBootstrapper
{ {
protected null|string $originalPrefix = null; protected string|null $originalPrefix = null;
protected string $storeName; protected string $storeName;
public function __construct( public function __construct(
protected Application $app,
protected Repository $config, protected Repository $config,
protected CacheManager $cacheManager,
) { ) {
} }
@ -36,21 +35,30 @@ class PrefixCacheTenancyBootstrapper implements TenancyBootstrapper
$this->originalPrefix = null; $this->originalPrefix = null;
} }
protected function setCachePrefix(null|string $prefix): void protected function syncStore(): void
{
$originalRepository = $this->cacheManager->driver($this->storeName);
// Delete the repository from CacheManager's $stores cache
// So that it's forced to resolve the repository again on the next attempt to get it
$this->cacheManager->forgetDriver($this->storeName);
// Let CacheManager create a repository with a fresh store
// To get a new store that uses the current value of `config('cache.prefix')` as the prefix
$newRepository = $this->cacheManager->driver($this->storeName);
// Give the new store to the old repository
$originalRepository->setStore($newRepository->getStore());
// Overwrite the new repository with the modified old one
$this->cacheManager->setStore($this->storeName, $originalRepository);
}
protected function setCachePrefix(string|null $prefix): void
{ {
$this->config->set('cache.prefix', $prefix); $this->config->set('cache.prefix', $prefix);
$this->app['cache']->forgetDriver($this->storeName); $this->syncStore();
// The CacheManager will have the $app['config'] array cached with old prefixes on the 'cache' instance
// This call will forget the 'cache' instance
$this->app->forgetInstance('cache');
// The Cache Repository is using an old version of the CacheManager so we need to forget it
$this->app->forgetInstance('cache.store');
// Forget the cache repository in the container to cover some edge-cases
$this->app->forgetInstance(CacheRepository::class);
// It is needed when a call to the facade has been made before bootstrapping tenancy // It is needed when a call to the facade has been made before bootstrapping tenancy
// The facade has its own cache, separate from the container // The facade has its own cache, separate from the container

View file

@ -26,7 +26,7 @@ test('cache prefix is separate for each tenant', function () {
$originalPrefix = config('cache.prefix'); $originalPrefix = config('cache.prefix');
$prefixBase = config('tenancy.cache.prefix_base'); $prefixBase = config('tenancy.cache.prefix_base');
expect($originalPrefix . ':') // cache manager postfix ':' to prefix expect($originalPrefix . ':') // RedisStore suffixes prefix with ':'
->toBe(app('cache')->getPrefix()) ->toBe(app('cache')->getPrefix())
->toBe(app('cache.store')->getPrefix()); ->toBe(app('cache.store')->getPrefix());
@ -53,7 +53,9 @@ test('cache prefix is separate for each tenant', function () {
// Assert tenants' data is accessible using the prefix from the central context // Assert tenants' data is accessible using the prefix from the central context
tenancy()->end(); tenancy()->end();
config(['cache.prefix' => null]); // stop prefixing cache keys in central so we can provide prefix manually config(['cache.prefix' => null]); // stop prefixing cache keys in central so we can provide prefix manually
app('cache')->forgetDriver(config('cache.default'));
expect(cache($tenantOnePrefix . ':key'))->toBe('tenantone-value'); expect(cache($tenantOnePrefix . ':key'))->toBe('tenantone-value');
expect(cache($tenantTwoPrefix . ':key'))->toBe('tenanttwo-value'); expect(cache($tenantTwoPrefix . ':key'))->toBe('tenanttwo-value');