cache = new PaginatedQueryCache( new TagAwareAdapter(new ArrayAdapter()), ); } #[Test] public function loadsFromCallableOnCacheMiss(): void { $expected = new PaginatedResult(items: ['item1'], total: 1, page: 1, limit: 30); $callCount = 0; $result = $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], static function () use ($expected, &$callCount): PaginatedResult { ++$callCount; return $expected; }); self::assertSame($expected, $result); self::assertSame(1, $callCount); } #[Test] public function returnsCachedResultOnHit(): void { $expected = new PaginatedResult(items: ['item1'], total: 1, page: 1, limit: 30); $callCount = 0; $loader = static function () use ($expected, &$callCount): PaginatedResult { ++$callCount; return $expected; }; $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $loader); $result = $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $loader); self::assertSame(1, $callCount); self::assertEquals($expected, $result); } #[Test] public function differentParamsProduceDifferentCacheEntries(): void { $result1 = new PaginatedResult(items: ['page1'], total: 2, page: 1, limit: 1); $result2 = new PaginatedResult(items: ['page2'], total: 2, page: 2, limit: 1); $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], static fn (): PaginatedResult => $result1); $actual = $this->cache->getOrLoad('users', 'tenant-1', ['page' => 2], static fn (): PaginatedResult => $result2); self::assertEquals($result2, $actual); } #[Test] public function invalidatesCacheByEntityTypeAndTenant(): void { $callCount = 0; $loader = static function () use (&$callCount): PaginatedResult { ++$callCount; return new PaginatedResult(items: [], total: 0, page: 1, limit: 30); }; $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $loader); self::assertSame(1, $callCount); $this->cache->invalidate('users', 'tenant-1'); $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $loader); self::assertSame(2, $callCount); } #[Test] public function invalidationDoesNotAffectOtherEntityTypes(): void { $usersCallCount = 0; $classesCallCount = 0; $usersLoader = static function () use (&$usersCallCount): PaginatedResult { ++$usersCallCount; return new PaginatedResult(items: [], total: 0, page: 1, limit: 30); }; $classesLoader = static function () use (&$classesCallCount): PaginatedResult { ++$classesCallCount; return new PaginatedResult(items: [], total: 0, page: 1, limit: 30); }; $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $usersLoader); $this->cache->getOrLoad('classes', 'tenant-1', ['page' => 1], $classesLoader); $this->cache->invalidate('users', 'tenant-1'); $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $usersLoader); $this->cache->getOrLoad('classes', 'tenant-1', ['page' => 1], $classesLoader); self::assertSame(2, $usersCallCount); self::assertSame(1, $classesCallCount); } #[Test] public function invalidationDoesNotAffectOtherTenants(): void { $tenant1Count = 0; $tenant2Count = 0; $tenant1Loader = static function () use (&$tenant1Count): PaginatedResult { ++$tenant1Count; return new PaginatedResult(items: [], total: 0, page: 1, limit: 30); }; $tenant2Loader = static function () use (&$tenant2Count): PaginatedResult { ++$tenant2Count; return new PaginatedResult(items: [], total: 0, page: 1, limit: 30); }; $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $tenant1Loader); $this->cache->getOrLoad('users', 'tenant-2', ['page' => 1], $tenant2Loader); $this->cache->invalidate('users', 'tenant-1'); $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1], $tenant1Loader); $this->cache->getOrLoad('users', 'tenant-2', ['page' => 1], $tenant2Loader); self::assertSame(2, $tenant1Count); self::assertSame(1, $tenant2Count); } #[Test] public function paramOrderDoesNotAffectCacheKey(): void { $callCount = 0; $loader = static function () use (&$callCount): PaginatedResult { ++$callCount; return new PaginatedResult(items: [], total: 0, page: 1, limit: 30); }; $this->cache->getOrLoad('users', 'tenant-1', ['page' => 1, 'role' => 'admin'], $loader); $this->cache->getOrLoad('users', 'tenant-1', ['role' => 'admin', 'page' => 1], $loader); self::assertSame(1, $callCount); } }