mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 15:34:03 +00:00
Add check to invalidateCache()
This commit is contained in:
parent
5d94727ddd
commit
ba7257670f
4 changed files with 89 additions and 45 deletions
|
|
@ -48,6 +48,10 @@ abstract class CachedTenantResolver implements TenantResolver
|
||||||
|
|
||||||
public function invalidateCache(Tenant $tenant): void
|
public function invalidateCache(Tenant $tenant): void
|
||||||
{
|
{
|
||||||
|
if (! static::$shouldCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->getArgsForTenant($tenant) as $args) {
|
foreach ($this->getArgsForTenant($tenant) as $args) {
|
||||||
$this->cache->forget($this->getCacheKey(...$args));
|
$this->cache->forget($this->getCacheKey(...$args));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,20 @@ namespace Stancl\Tenancy\Resolvers;
|
||||||
|
|
||||||
use Stancl\Tenancy\Contracts\Domain;
|
use Stancl\Tenancy\Contracts\Domain;
|
||||||
use Stancl\Tenancy\Contracts\Tenant;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
use Stancl\Tenancy\Contracts\TenantResolver;
|
|
||||||
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
|
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
|
||||||
|
|
||||||
class DomainTenantResolver implements TenantResolver
|
class DomainTenantResolver extends Contracts\CachedTenantResolver
|
||||||
{
|
{
|
||||||
public function resolve(...$args): Tenant
|
/** @var bool */
|
||||||
|
public static $shouldCache = false;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public static $cacheTTL = 3600; // seconds
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
public static $cacheStore = null; // default
|
||||||
|
|
||||||
|
public function resolveWithoutCache(...$args): Tenant
|
||||||
{
|
{
|
||||||
/** @var Domain $domain */
|
/** @var Domain $domain */
|
||||||
$domain = config('tenancy.domain_model')::where('domain', $args[0])->first();
|
$domain = config('tenancy.domain_model')::where('domain', $args[0])->first();
|
||||||
|
|
@ -22,4 +30,13 @@ class DomainTenantResolver implements TenantResolver
|
||||||
|
|
||||||
throw new TenantCouldNotBeIdentifiedOnDomainException($domain);
|
throw new TenantCouldNotBeIdentifiedOnDomainException($domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getArgsForTenant(Tenant $tenant): array
|
||||||
|
{
|
||||||
|
$tenant->unsetRelation('domains');
|
||||||
|
|
||||||
|
return $tenant->domains->map(function (Domain $domain) {
|
||||||
|
return [$domain->domain];
|
||||||
|
})->toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class PostgreSQLSchemaManager implements TenantDatabaseManager
|
||||||
|
|
||||||
public function deleteDatabase(TenantWithDatabase $tenant): bool
|
public function deleteDatabase(TenantWithDatabase $tenant): bool
|
||||||
{
|
{
|
||||||
return $this->database()->statement("DROP SCHEMA \"{$tenant->database()->getName()}\"");
|
return $this->database()->statement("DROP SCHEMA \"{$tenant->database()->getName()}\" CASCADE");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function databaseExists(string $name): bool
|
public function databaseExists(string $name): bool
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
|
||||||
use Stancl\Tenancy\Resolvers\CachedTenantResolver;
|
|
||||||
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
||||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
|
||||||
|
|
@ -15,8 +12,7 @@ class CachedTenantResolverTest extends TestCase
|
||||||
{
|
{
|
||||||
public function tearDown(): void
|
public function tearDown(): void
|
||||||
{
|
{
|
||||||
InitializeTenancyByDomain::$shouldCache = false;
|
DomainTenantResolver::$shouldCache = false;
|
||||||
InitializeTenancyByRequestData::$shouldCache = false;
|
|
||||||
|
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +26,7 @@ class CachedTenantResolverTest extends TestCase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
$this->assertTrue($tenant->is(app(CachedTenantResolver::class)->resolve(DomainTenantResolver::class, ['acme'])));
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|
@ -41,51 +37,78 @@ class CachedTenantResolverTest extends TestCase
|
||||||
'domain' => 'acme',
|
'domain' => 'acme',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertTrue($tenant->is(app(CachedTenantResolver::class)->resolve(DomainTenantResolver::class, ['acme'])));
|
DB::enableQueryLog();
|
||||||
|
|
||||||
$this->mock(DomainTenantResolver::class, function ($mock) {
|
DomainTenantResolver::$shouldCache = false;
|
||||||
return $mock->shouldNotReceive('resolve');
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->assertTrue($tenant->is(app(CachedTenantResolver::class)->resolve(DomainTenantResolver::class, ['acme'])));
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
DB::flushQueryLog();
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
$this->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||||
|
|
||||||
|
DomainTenantResolver::$shouldCache = true;
|
||||||
|
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
DB::flushQueryLog();
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
$this->assertEmpty(DB::getQueryLog()); // empty
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function caching_can_be_configured_selectively_on_initialization_middleware()
|
public function cache_is_invalidated_when_the_tenant_is_updated()
|
||||||
{
|
{
|
||||||
InitializeTenancyByDomain::$shouldCache = true;
|
$tenant = Tenant::create();
|
||||||
|
$tenant->createDomain([
|
||||||
$tenant = Tenant::create([
|
'domain' => 'acme',
|
||||||
'id' => 'acme',
|
|
||||||
]);
|
|
||||||
$tenant->domains()->create([
|
|
||||||
'domain' => 'acme.localhost',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Route::get('/foo', function () {
|
DB::enableQueryLog();
|
||||||
return 'bar';
|
|
||||||
})->middleware(InitializeTenancyByDomain::class);
|
|
||||||
|
|
||||||
// create cache
|
DomainTenantResolver::$shouldCache = true;
|
||||||
$this->get('http://acme.localhost/foo')
|
|
||||||
->assertSee('bar');
|
|
||||||
|
|
||||||
$this->mock(CachedTenantResolver::class, function ($mock) {
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
return $mock->shouldReceive('resolve')->once(); // only once
|
DB::flushQueryLog();
|
||||||
});
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
$this->assertEmpty(DB::getQueryLog()); // empty
|
||||||
|
|
||||||
// use cache
|
$tenant->update([
|
||||||
$this->get('http://acme.localhost/foo')
|
'foo' => 'bar',
|
||||||
->assertSee('bar');
|
]);
|
||||||
|
|
||||||
Route::get('/abc', function () {
|
DB::flushQueryLog();
|
||||||
return 'xyz';
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
})->middleware(InitializeTenancyByRequestData::class);
|
$this->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||||
|
|
||||||
$this->get('/abc?tenant=acme')
|
|
||||||
->assertSee('xyz');
|
|
||||||
|
|
||||||
$this->get('/abc?tenant=acme')
|
|
||||||
->assertSee('xyz');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function cache_is_invalidated_when_a_tenants_domain_is_changed()
|
||||||
|
{
|
||||||
|
$tenant = Tenant::create();
|
||||||
|
$tenant->createDomain([
|
||||||
|
'domain' => 'acme',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::enableQueryLog();
|
||||||
|
|
||||||
|
DomainTenantResolver::$shouldCache = true;
|
||||||
|
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
DB::flushQueryLog();
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
$this->assertEmpty(DB::getQueryLog()); // empty
|
||||||
|
|
||||||
|
$tenant->createDomain([
|
||||||
|
'domain' => 'bar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::flushQueryLog();
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||||
|
$this->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||||
|
|
||||||
|
DB::flushQueryLog();
|
||||||
|
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('bar')));
|
||||||
|
$this->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo2 at some point in the future, we could write invalidation tests for the other resolvers too
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue