mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 15:34:04 +00:00
wip cache invalidation
This commit is contained in:
parent
a99f5d916d
commit
a6102be1a0
4 changed files with 124 additions and 20 deletions
|
|
@ -42,5 +42,28 @@ class CachedTenantResolver
|
||||||
return Tenant::fromStorage($data)->withDomains($domains);
|
return Tenant::fromStorage($data)->withDomains($domains);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function invalidateTenant(string $id): void
|
||||||
|
{
|
||||||
|
$this->invalidateTenantData($id);
|
||||||
|
$this->invalidateTenantDomains($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invalidateTenantData(string $id): void
|
||||||
|
{
|
||||||
|
$this->cache->forget('_tenancy_id_to_data:' . $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invalidateTenantDomains(string $id): void
|
||||||
|
{
|
||||||
|
$this->cache->forget('_tenancy_id_to_domains:' . $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invalidateDomainToIdMapping(array $domains): void
|
||||||
|
{
|
||||||
|
foreach ($domains as $domain) {
|
||||||
|
$this->cache->forget('_tenancy_domain_to_id:' . $domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// todo update cache on writes to data & domains
|
// todo update cache on writes to data & domains
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,11 +152,18 @@ class DatabaseStorageDriver implements StorageDriver, CanDeleteKeys, CanFindByAn
|
||||||
|
|
||||||
public function updateTenant(Tenant $tenant): void
|
public function updateTenant(Tenant $tenant): void
|
||||||
{
|
{
|
||||||
$this->centralDatabase->transaction(function () use ($tenant) {
|
$originalDomains = $this->domains->getTenantDomains($tenant);
|
||||||
|
|
||||||
|
$this->centralDatabase->transaction(function () use ($tenant, $originalDomains) {
|
||||||
$this->tenants->updateTenant($tenant);
|
$this->tenants->updateTenant($tenant);
|
||||||
|
|
||||||
$this->domains->updateTenantDomains($tenant);
|
$this->domains->updateTenantDomains($tenant, $originalDomains);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if ($this->usesCache()) {
|
||||||
|
$this->cache->invalidateTenant($tenant->id);
|
||||||
|
$this->cache->invalidateDomainToIdMapping($originalDomains);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteTenant(Tenant $tenant): void
|
public function deleteTenant(Tenant $tenant): void
|
||||||
|
|
@ -203,17 +210,32 @@ class DatabaseStorageDriver implements StorageDriver, CanDeleteKeys, CanFindByAn
|
||||||
|
|
||||||
public function put(string $key, $value, Tenant $tenant = null): void
|
public function put(string $key, $value, Tenant $tenant = null): void
|
||||||
{
|
{
|
||||||
$this->tenants->put($key, $value, $tenant ?? $this->currentTenant());
|
$tenant = $tenant ?? $this->currentTenant();
|
||||||
|
$this->tenants->put($key, $value, $tenant);
|
||||||
|
|
||||||
|
if ($this->usesCache()) {
|
||||||
|
$this->cache->invalidateTenantData($tenant->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function putMany(array $kvPairs, Tenant $tenant = null): void
|
public function putMany(array $kvPairs, Tenant $tenant = null): void
|
||||||
{
|
{
|
||||||
$this->tenants->putMany($kvPairs, $tenant ?? $this->currentTenant());
|
$tenant = $tenant ?? $this->currentTenant();
|
||||||
|
$this->tenants->putMany($kvPairs, $tenant);
|
||||||
|
|
||||||
|
if ($this->usesCache()) {
|
||||||
|
$this->cache->invalidateTenantData($tenant->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteMany(array $keys, Tenant $tenant = null): void
|
public function deleteMany(array $keys, Tenant $tenant = null): void
|
||||||
{
|
{
|
||||||
$this->tenants->deleteMany($keys, $tenant ?? $this->currentTenant());
|
$tenant = $tenant ?? $this->currentTenant();
|
||||||
|
$this->tenants->deleteMany($keys, $tenant);
|
||||||
|
|
||||||
|
if ($this->usesCache()) {
|
||||||
|
$this->cache->invalidateTenantData($tenant->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function usesCache(): bool
|
public function usesCache(): bool
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,8 @@ class DomainRepository extends Repository
|
||||||
}, $tenant->domains));
|
}, $tenant->domains));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateTenantDomains(Tenant $tenant)
|
public function updateTenantDomains(Tenant $tenant, array $originalDomains)
|
||||||
{
|
{
|
||||||
$originalDomains = $this->getTenantDomains($tenant);
|
|
||||||
$deletedDomains = array_diff($originalDomains, $tenant->domains);
|
$deletedDomains = array_diff($originalDomains, $tenant->domains);
|
||||||
$newDomains = array_diff($tenant->domains, $originalDomains);
|
$newDomains = array_diff($tenant->domains, $originalDomains);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Stancl\Tenancy\StorageDrivers\Database\DatabaseStorageDriver;
|
||||||
use Stancl\Tenancy\Tenant;
|
use Stancl\Tenancy\Tenant;
|
||||||
|
|
||||||
class CachedResolverTest extends TestCase
|
class CachedResolverTest extends TestCase
|
||||||
|
|
@ -23,43 +25,101 @@ class CachedResolverTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function a_query_is_not_made_for_tenant_id_once_domain_is_cached()
|
public function a_query_is_not_made_for_tenant_id_once_domain_is_cached()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::new()->withDomains(['foo.localhost'])->save();
|
$tenant = Tenant::new()
|
||||||
|
->withData(['foo' => 'bar'])
|
||||||
|
->withDomains(['foo.localhost'])
|
||||||
|
->save();
|
||||||
|
|
||||||
// todo assert query is made:
|
// query is made
|
||||||
$queried = tenancy()->findByDomain('foo.localhost');
|
$queried = tenancy()->findByDomain('foo.localhost');
|
||||||
|
$this->assertEquals($tenant->data, $queried->data);
|
||||||
|
$this->assertSame($tenant->domains, $queried->domains);
|
||||||
|
|
||||||
// todo assert query is not made but cache call is made:
|
// cache is set
|
||||||
|
$this->assertEquals($tenant->data, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||||
|
$this->assertSame($tenant->domains, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||||
|
|
||||||
|
// query is not made
|
||||||
|
DatabaseStorageDriver::getCentralConnection()->enableQueryLog();
|
||||||
$cached = tenancy()->findByDomain('foo.localhost');
|
$cached = tenancy()->findByDomain('foo.localhost');
|
||||||
|
$this->assertEquals($tenant->data, $cached->data);
|
||||||
|
$this->assertSame($tenant->domains, $cached->domains);
|
||||||
|
$this->assertSame([], DatabaseStorageDriver::getCentralConnection()->getQueryLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function a_query_is_not_made_for_tenant_once_id_is_cached()
|
public function a_query_is_not_made_for_tenant_once_id_is_cached()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::new()->withData(['id' => '123'])->save();
|
$tenant = Tenant::new()
|
||||||
|
->withData(['foo' => 'bar'])
|
||||||
|
->withDomains(['foo.localhost'])
|
||||||
|
->save();
|
||||||
|
|
||||||
// todo assert query is made:
|
// query is made
|
||||||
$queried = tenancy()->find('123');
|
$queried = tenancy()->find($tenant->id);
|
||||||
|
$this->assertEquals($tenant->data, $queried->data);
|
||||||
|
$this->assertSame($tenant->domains, $queried->domains);
|
||||||
|
|
||||||
// todo assert query is not made but cache call is made:
|
// cache is set
|
||||||
$cached = tenancy()->find('123');
|
$this->assertEquals($tenant->data, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||||
|
$this->assertSame($tenant->domains, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||||
|
|
||||||
|
// query is not made
|
||||||
|
DatabaseStorageDriver::getCentralConnection()->enableQueryLog();
|
||||||
|
$cached = tenancy()->find($tenant->id);
|
||||||
|
$this->assertEquals($tenant->data, $cached->data);
|
||||||
|
$this->assertSame($tenant->domains, $cached->domains);
|
||||||
|
$this->assertSame([], DatabaseStorageDriver::getCentralConnection()->getQueryLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function modifying_tenants_domains_updates_domains_in_the_cached_domain_to_id_mapping()
|
public function modifying_tenants_domains_updates_domains_in_the_cached_domain_to_id_mapping()
|
||||||
{
|
{
|
||||||
|
// todo adding domain adds mapping
|
||||||
|
// todo removing domain removes mapping
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function modifying_tenants_data_updates_data_in_the_cached_id_to_tenant_data_mapping()
|
public function modifying_tenants_data_updates_data_in_the_cached_id_to_tenant_data_mapping()
|
||||||
{
|
{
|
||||||
$tenant = Tenant::new()->withData(['id' => '123', 'foo' => 'bar'])->save();
|
$tenant = Tenant::new()->withData(['foo' => 'bar'])->save();
|
||||||
|
|
||||||
// todo assert cache record is set
|
// cache record is set
|
||||||
$this->assertSame('bar', tenancy()->find('123')->get('foo'));
|
$this->assertSame('bar', tenancy()->find($tenant->id)->get('foo'));
|
||||||
|
$this->assertSame('bar', Cache::get('_tenancy_id_to_data:' . $tenant->id)['foo']);
|
||||||
|
|
||||||
// todo assert cache record is updated
|
// cache record is invalidated
|
||||||
$tenant->set('foo', 'xyz');
|
$tenant->set('foo', 'xyz');
|
||||||
|
$this->assertSame(null, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||||
|
|
||||||
$this->assertSame('xyz', tenancy()->find('123')->get('foo'));
|
// cache record is set
|
||||||
|
$this->assertSame('xyz', tenancy()->find($tenant->id)->get('foo'));
|
||||||
|
$this->assertSame('xyz', Cache::get('_tenancy_id_to_data:' . $tenant->id)['foo']);
|
||||||
|
|
||||||
|
// cache record is invalidated
|
||||||
|
$tenant->foo = 'abc';
|
||||||
|
$tenant->save();
|
||||||
|
$this->assertSame(null, Cache::get('_tenancy_id_to_data:' . $tenant->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function modifying_tenants_domains_updates_domains_in_the_cached_id_to_tenant_domains_mapping()
|
||||||
|
{
|
||||||
|
$tenant = Tenant::new()
|
||||||
|
->withData(['foo' => 'bar'])
|
||||||
|
->withDomains(['foo.localhost'])
|
||||||
|
->save();
|
||||||
|
|
||||||
|
// cache record is set
|
||||||
|
$this->assertSame(['foo.localhost'], tenancy()->find($tenant->id)->domains);
|
||||||
|
$this->assertSame(['foo.localhost'], Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||||
|
|
||||||
|
// cache record is invalidated
|
||||||
|
$tenant->addDomains(['bar.localhost'])->save();
|
||||||
|
$this->assertEquals(null, Cache::get('_tenancy_id_to_domains:' . $tenant->id));
|
||||||
|
|
||||||
|
$this->assertEquals(['foo.localhost', 'bar.localhost'], tenancy()->find($tenant->id)->domains);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo deleting tenant invalidates all caches
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue