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

Run all cached resolver/global cache tests with DatabaseCacheBootstrapper

This commit is contained in:
Samuel Štancl 2025-08-06 18:44:56 +02:00
parent 999caa65d9
commit b7df2ca436
4 changed files with 59 additions and 24 deletions

View file

@ -17,6 +17,9 @@ abstract class CachedTenantResolver implements TenantResolver
public function __construct(Application $app)
{
// globalCache should generally not be injected, however in this case
// the class is always created from scratch when calling invalidateCache()
// meaning the global cache stores are also resolved from scratch.
$this->cache = $app->make('globalCache')->store(static::cacheStore());
}

View file

@ -83,10 +83,6 @@ class TenancyServiceProvider extends ServiceProvider
return new Commands\Seed($app['db']);
});
// todo0 check what happens if globalCache is injected - it may be
// problematic if it's injected before adjustCacheManagerUsing
// was used
$this->app->bind('globalCache', function ($app) {
// We create a separate CacheManager to be used for "global" cache -- cache that
// is always central, regardless of the current context.

View file

@ -14,6 +14,8 @@ use Illuminate\Support\Facades\Route as RouteFacade;
use Illuminate\Support\Facades\Schema;
use Stancl\Tenancy\Bootstrappers\CacheTagsBootstrapper;
use Stancl\Tenancy\Bootstrappers\CacheTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\DatabaseCacheBootstrapper;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Events\TenancyInitialized;
@ -23,6 +25,8 @@ use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
use Stancl\Tenancy\Resolvers\RequestDataTenantResolver;
use function Stancl\Tenancy\Tests\pest;
use function Stancl\Tenancy\Tests\withCacheTables;
use function Stancl\Tenancy\Tests\withTenantDatabases;
beforeEach($cleanup = function () {
Tenant::$extraCustomColumns = [];
@ -112,11 +116,19 @@ test('cache is invalidated when the tenant is updated', function (string $resolv
// Only testing update here - presumably if this works, deletes (and other things we test here)
// will work as well. The main unique thing about this test is that it makes the change from
// *within* the tenant context.
test('cache is invalidated when tenant is updated from within the tenant context', function (string $cacheBootstrapper) {
config(['tenancy.bootstrappers' => [$cacheBootstrapper]]);
test('cache is invalidated when tenant is updated from within the tenant context', function (string $cacheStore, array $bootstrappers) {
config([
'cache.default' => $cacheStore,
'tenancy.bootstrappers' => $bootstrappers,
]);
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
if ($cacheStore === 'database') {
withCacheTables();
withTenantDatabases();
}
$resolver = PathTenantResolver::class;
$tenant = Tenant::create([$tenantModelColumn = tenantModelColumn(true) => 'acme']);
@ -150,9 +162,9 @@ test('cache is invalidated when tenant is updated from within the tenant context
expect(DB::getQueryLog())->not()->toBeEmpty(); // Cache was invalidated, so the tenant was retrieved from the DB
})->with([
// todo0 test this with the database cache bootstrapper too?
CacheTenancyBootstrapper::class,
CacheTagsBootstrapper::class,
['redis', [CacheTenancyBootstrapper::class]],
['redis', [CacheTagsBootstrapper::class]],
['database', [DatabaseTenancyBootstrapper::class, DatabaseCacheBootstrapper::class]],
]);
test('cache is invalidated when the tenant is deleted', function (string $resolver, bool $configureTenantModelColumn) {

View file

@ -29,8 +29,13 @@ beforeEach(function () {
withCacheTables();
});
test('global cache manager stores data in global cache', function (string $bootstrapper) {
config(['tenancy.bootstrappers' => [$bootstrapper]]);
test('global cache manager stores data in global cache', function (string $store, array $bootstrappers) {
config([
'cache.default' => $store,
'tenancy.bootstrappers' => $bootstrappers,
]);
if ($store === 'database') withTenantDatabases(true);
expect(cache('foo'))->toBe(null);
GlobalCache::put('foo', 'bar');
@ -44,9 +49,16 @@ test('global cache manager stores data in global cache', function (string $boots
cache(['def' => 'ghi'], 10);
expect(cache('def'))->toBe('ghi');
// different stores, same underlying connection. the prefix is set ON THE STORE
// different stores
expect(cache()->store()->getStore() !== GlobalCache::store()->getStore())->toBeTrue();
expect(cache()->store()->getStore()->connection() === GlobalCache::store()->getStore()->connection())->toBeTrue();
if ($store === 'redis') {
// same underlying connection. the prefix is set ON THE STORE
expect(cache()->store()->getStore()->connection() === GlobalCache::store()->getStore()->connection())->toBeTrue();
} else {
// different connections
expect(cache()->store()->getStore()->getConnection()->getName())->toBe('tenant');
expect(GlobalCache::store()->getStore()->getConnection()->getName())->toBe('central');
}
tenancy()->end();
expect(GlobalCache::get('abc'))->toBe('xyz');
@ -64,8 +76,9 @@ test('global cache manager stores data in global cache', function (string $boots
tenancy()->initialize($tenant1);
expect(cache('def'))->toBe('ghi');
})->with([
CacheTagsBootstrapper::class,
CacheTenancyBootstrapper::class,
['redis', [CacheTagsBootstrapper::class]],
['redis', [CacheTenancyBootstrapper::class]],
['database', [DatabaseTenancyBootstrapper::class, DatabaseCacheBootstrapper::class]],
]);
test('global cache facade is not persistent', function () {
@ -76,8 +89,6 @@ test('global cache facade is not persistent', function () {
expect(spl_object_id(GlobalCache::getFacadeRoot()))->not()->toBe($oldId);
});
// todo0 add database cache bootstrapper to other tests
test('global cache is always central', function (string $store, array $bootstrappers, string $initialCentralCall) {
config([
'cache.default' => $store,
@ -161,15 +172,27 @@ test('global cache is always central', function (string $store, array $bootstrap
'none',
]);
test('the global_cache helper supports the same syntax as the cache helper', function (string $bootstrapper) {
config(['tenancy.bootstrappers' => [$bootstrapper]]);
test('the global_cache helper supports the same syntax as the cache helper', function (string $store, array $bootstrappers) {
config([
'cache.default' => $store,
'tenancy.bootstrappers' => $bootstrappers,
]);
if ($store === 'database') withTenantDatabases(true);
$tenant = Tenant::create();
$tenant->enter();
// different stores, same underlying connection. the prefix is set ON THE STORE
expect(cache()->store()->getStore() !== global_cache()->store()->getStore())->toBeTrue();
expect(cache()->store()->getStore()->connection() === global_cache()->store()->getStore()->connection())->toBeTrue();
// different stores
expect(cache()->store()->getStore() !== GlobalCache::store()->getStore())->toBeTrue();
if ($store === 'redis') {
// same underlying connection. the prefix is set ON THE STORE
expect(cache()->store()->getStore()->connection() === global_cache()->store()->getStore()->connection())->toBeTrue();
} else {
// different connections
expect(cache()->store()->getStore()->getConnection()->getName())->toBe('tenant');
expect(global_cache()->store()->getStore()->getConnection()->getName())->toBe('central');
}
expect(cache('foo'))->toBe(null); // tenant cache is empty
@ -181,6 +204,7 @@ test('the global_cache helper supports the same syntax as the cache helper', fun
expect(cache('foo'))->toBe(null); // tenant cache is not affected
})->with([
CacheTagsBootstrapper::class,
CacheTenancyBootstrapper::class,
['redis', [CacheTagsBootstrapper::class]],
['redis', [CacheTenancyBootstrapper::class]],
['database', [DatabaseTenancyBootstrapper::class, DatabaseCacheBootstrapper::class]],
]);