fix(demo): invalidate paginated caches after seeding
Invalidate tenant read-model caches after generating demo data so seeded users, classes and assignments appear immediately in the UI.
This commit is contained in:
@@ -6,6 +6,7 @@ namespace App\Administration\Infrastructure\Service;
|
|||||||
|
|
||||||
use App\Administration\Application\Port\OfficialCalendarProvider;
|
use App\Administration\Application\Port\OfficialCalendarProvider;
|
||||||
use App\Administration\Application\Port\PasswordHasher;
|
use App\Administration\Application\Port\PasswordHasher;
|
||||||
|
use App\Administration\Application\Service\Cache\PaginatedQueryCache;
|
||||||
use App\Administration\Domain\Model\AcademicYear\DefaultPeriods;
|
use App\Administration\Domain\Model\AcademicYear\DefaultPeriods;
|
||||||
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
||||||
use App\Administration\Domain\Model\ClassAssignment\ClassAssignment;
|
use App\Administration\Domain\Model\ClassAssignment\ClassAssignment;
|
||||||
@@ -69,6 +70,7 @@ final readonly class DemoDataGenerator
|
|||||||
private \App\Administration\Domain\Model\SchoolCalendar\SchoolCalendarRepository $schoolCalendarRepository,
|
private \App\Administration\Domain\Model\SchoolCalendar\SchoolCalendarRepository $schoolCalendarRepository,
|
||||||
private GradingConfigurationRepository $gradingConfigurationRepository,
|
private GradingConfigurationRepository $gradingConfigurationRepository,
|
||||||
private PasswordHasher $passwordHasher,
|
private PasswordHasher $passwordHasher,
|
||||||
|
private PaginatedQueryCache $paginatedQueryCache,
|
||||||
private Clock $clock,
|
private Clock $clock,
|
||||||
private TenantContext $tenantContext,
|
private TenantContext $tenantContext,
|
||||||
private CurrentAcademicYearResolver $currentAcademicYearResolver,
|
private CurrentAcademicYearResolver $currentAcademicYearResolver,
|
||||||
@@ -114,6 +116,7 @@ final readonly class DemoDataGenerator
|
|||||||
$this->seedTeacherAssignments($tenantId, $academicYearId, $users, $classes, $subjects, $now, $result);
|
$this->seedTeacherAssignments($tenantId, $academicYearId, $users, $classes, $subjects, $now, $result);
|
||||||
$this->seedStudentGuardianLinks($tenantId, $users, $now, $result);
|
$this->seedStudentGuardianLinks($tenantId, $users, $now, $result);
|
||||||
$this->seedScheduleSlots($tenantId, $classes, $subjects, $users, $academicYearStartYear, $now, $result);
|
$this->seedScheduleSlots($tenantId, $classes, $subjects, $users, $academicYearStartYear, $now, $result);
|
||||||
|
$this->invalidateReadModelCaches((string) $tenantId);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -667,6 +670,20 @@ final readonly class DemoDataGenerator
|
|||||||
return $startYear;
|
return $startYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function invalidateReadModelCaches(string $tenantId): void
|
||||||
|
{
|
||||||
|
foreach ([
|
||||||
|
'users',
|
||||||
|
'classes',
|
||||||
|
'subjects',
|
||||||
|
'assignments',
|
||||||
|
'parent_invitations',
|
||||||
|
'students_image_rights',
|
||||||
|
] as $entityType) {
|
||||||
|
$this->paginatedQueryCache->invalidate($entityType, $tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function emailFor(string $emailSlug, string $subdomain): string
|
private function emailFor(string $emailSlug, string $subdomain): string
|
||||||
{
|
{
|
||||||
return sprintf('%s.%s@classeo.test', strtolower($emailSlug), strtolower($subdomain));
|
return sprintf('%s.%s@classeo.test', strtolower($emailSlug), strtolower($subdomain));
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Tests\Unit\Administration\Infrastructure\Service;
|
namespace App\Tests\Unit\Administration\Infrastructure\Service;
|
||||||
|
|
||||||
|
use App\Administration\Application\Dto\PaginatedResult;
|
||||||
use App\Administration\Application\Port\OfficialCalendarProvider;
|
use App\Administration\Application\Port\OfficialCalendarProvider;
|
||||||
use App\Administration\Application\Port\PasswordHasher;
|
use App\Administration\Application\Port\PasswordHasher;
|
||||||
|
use App\Administration\Application\Service\Cache\PaginatedQueryCache;
|
||||||
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
use App\Administration\Domain\Model\AcademicYear\PeriodType;
|
||||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntry;
|
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntry;
|
||||||
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryId;
|
use App\Administration\Domain\Model\SchoolCalendar\CalendarEntryId;
|
||||||
@@ -34,6 +36,8 @@ use DateTimeImmutable;
|
|||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||||
|
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
|
||||||
|
|
||||||
final class DemoDataGeneratorTest extends TestCase
|
final class DemoDataGeneratorTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -50,6 +54,7 @@ final class DemoDataGeneratorTest extends TestCase
|
|||||||
private InMemoryPeriodConfigurationRepository $periodConfigurationRepository;
|
private InMemoryPeriodConfigurationRepository $periodConfigurationRepository;
|
||||||
private InMemorySchoolCalendarRepository $schoolCalendarRepository;
|
private InMemorySchoolCalendarRepository $schoolCalendarRepository;
|
||||||
private GradingConfigurationRepository $gradingConfigurationRepository;
|
private GradingConfigurationRepository $gradingConfigurationRepository;
|
||||||
|
private PaginatedQueryCache $paginatedQueryCache;
|
||||||
private DemoDataGenerator $generator;
|
private DemoDataGenerator $generator;
|
||||||
private TenantConfig $tenantConfig;
|
private TenantConfig $tenantConfig;
|
||||||
|
|
||||||
@@ -65,6 +70,7 @@ final class DemoDataGeneratorTest extends TestCase
|
|||||||
$this->periodConfigurationRepository = new InMemoryPeriodConfigurationRepository();
|
$this->periodConfigurationRepository = new InMemoryPeriodConfigurationRepository();
|
||||||
$this->schoolCalendarRepository = new InMemorySchoolCalendarRepository();
|
$this->schoolCalendarRepository = new InMemorySchoolCalendarRepository();
|
||||||
$this->gradingConfigurationRepository = new InMemoryGradingConfigurationRepository();
|
$this->gradingConfigurationRepository = new InMemoryGradingConfigurationRepository();
|
||||||
|
$this->paginatedQueryCache = new PaginatedQueryCache(new TagAwareAdapter(new ArrayAdapter()));
|
||||||
|
|
||||||
$clock = new class implements Clock {
|
$clock = new class implements Clock {
|
||||||
public function now(): DateTimeImmutable
|
public function now(): DateTimeImmutable
|
||||||
@@ -136,6 +142,7 @@ final class DemoDataGeneratorTest extends TestCase
|
|||||||
schoolCalendarRepository: $this->schoolCalendarRepository,
|
schoolCalendarRepository: $this->schoolCalendarRepository,
|
||||||
gradingConfigurationRepository: $this->gradingConfigurationRepository,
|
gradingConfigurationRepository: $this->gradingConfigurationRepository,
|
||||||
passwordHasher: $passwordHasher,
|
passwordHasher: $passwordHasher,
|
||||||
|
paginatedQueryCache: $this->paginatedQueryCache,
|
||||||
clock: $clock,
|
clock: $clock,
|
||||||
tenantContext: $tenantContext,
|
tenantContext: $tenantContext,
|
||||||
currentAcademicYearResolver: $currentAcademicYearResolver,
|
currentAcademicYearResolver: $currentAcademicYearResolver,
|
||||||
@@ -255,6 +262,56 @@ final class DemoDataGeneratorTest extends TestCase
|
|||||||
self::assertCount(30, $result->accounts);
|
self::assertCount(30, $result->accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function itInvalidatesPaginatedReadModelCacheAfterGeneration(): void
|
||||||
|
{
|
||||||
|
$loadCount = 0;
|
||||||
|
|
||||||
|
$this->paginatedQueryCache->getOrLoad(
|
||||||
|
'users',
|
||||||
|
self::TENANT_ID,
|
||||||
|
['page' => 1, 'limit' => 30, 'role' => null, 'statut' => null, 'search' => null],
|
||||||
|
static function () use (&$loadCount): PaginatedResult {
|
||||||
|
++$loadCount;
|
||||||
|
|
||||||
|
return new PaginatedResult(
|
||||||
|
items: [],
|
||||||
|
total: 0,
|
||||||
|
page: 1,
|
||||||
|
limit: 30,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(1, $loadCount);
|
||||||
|
|
||||||
|
$this->generator->generate(
|
||||||
|
tenantConfig: $this->tenantConfig,
|
||||||
|
password: 'DemoPassword123!',
|
||||||
|
schoolName: 'Établissement Démo',
|
||||||
|
zone: SchoolZone::B,
|
||||||
|
periodType: PeriodType::TRIMESTER,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->paginatedQueryCache->getOrLoad(
|
||||||
|
'users',
|
||||||
|
self::TENANT_ID,
|
||||||
|
['page' => 1, 'limit' => 30, 'role' => null, 'statut' => null, 'search' => null],
|
||||||
|
static function () use (&$loadCount): PaginatedResult {
|
||||||
|
++$loadCount;
|
||||||
|
|
||||||
|
return new PaginatedResult(
|
||||||
|
items: [],
|
||||||
|
total: 30,
|
||||||
|
page: 1,
|
||||||
|
limit: 30,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame(2, $loadCount);
|
||||||
|
}
|
||||||
|
|
||||||
private function resolveCurrentAcademicYearId(): \App\Administration\Domain\Model\SchoolClass\AcademicYearId
|
private function resolveCurrentAcademicYearId(): \App\Administration\Domain\Model\SchoolClass\AcademicYearId
|
||||||
{
|
{
|
||||||
$tenantContext = new TenantContext();
|
$tenantContext = new TenantContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user