From 5ac8b44fb96ed93a226534ccb83612994d6ca051 Mon Sep 17 00:00:00 2001 From: Yassine R Date: Wed, 27 Dec 2023 12:31:17 +0100 Subject: [PATCH] fix(stats): add cache to stats --- .talismanrc | 4 +- .../db/dumps/domifa_test.postgres.custom.gz | Bin 91794 -> 91761 bytes ...domifa_test.postgres.restore-data-only.sql | 28 +- ...st.postgres.truncate-restore-data-only.sql | 28 +- .../1703081808851-manual-migration.ts | 2 +- .../usager/usagerRepository.service.ts | 4 +- .../stats.public.controller.spec.ts | 390 +++++++++--------- .../controllers/stats.public.controller.ts | 7 +- .../src/stats/services/publicStats.service.ts | 32 +- .../usagerHistoryStateManager.service.ts | 2 +- 10 files changed, 260 insertions(+), 237 deletions(-) diff --git a/.talismanrc b/.talismanrc index 41f48bab65..866969b9cf 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,8 +1,8 @@ fileignoreconfig: - filename: _scripts/db/dumps/domifa_test.postgres.restore-data-only.sql - checksum: f830f17c3ba34a7b96732625490c18b91d654a508c4c6d5f2d8ee98e658f3a8a + checksum: 1cdf7754b06271ad65a5f821a6140c6e7327a91cba16d980c2c39bdb40e75089 - filename: _scripts/db/dumps/domifa_test.postgres.truncate-restore-data-only.sql - checksum: 85bd13b83873b42839f02568ff1ce9f24c43b345ba94b78dc3638d83f9f30efd + checksum: 507d8ae2da670759be7035f4e6f6e0ee4568396ed65c9c843e4e7acddd83876f - filename: packages/backend/src/_common/decorators/IsValidPasswordDecorator.ts checksum: f0d4b3cd2e6e2d9b1e0271c34d64adacf87a5f1e7a505402a20869962543608d - filename: packages/backend/src/_migrations/1699910877010-auto-migration.ts diff --git a/_scripts/db/dumps/domifa_test.postgres.custom.gz b/_scripts/db/dumps/domifa_test.postgres.custom.gz index 72876e1c65235b962b5e1db627dff99f94142339..46b84405653c99788077ba4266a138bd83ccf86b 100644 GIT binary patch delta 6955 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 { + private async counteMigratedStats(): Promise { return usagerHistoryRepository.countBy({ migrated: false }); } } diff --git a/packages/backend/src/database/services/usager/usagerRepository.service.ts b/packages/backend/src/database/services/usager/usagerRepository.service.ts index ac46810a08..e74fb5c442 100644 --- a/packages/backend/src/database/services/usager/usagerRepository.service.ts +++ b/packages/backend/src/database/services/usager/usagerRepository.service.ts @@ -128,7 +128,7 @@ async function countTotalUsagers(structuresId?: number[]): Promise { } async function countTotalActifs(): Promise { - const usagers: [{ actifs: number }] = await usagerRepository.query(` + const usagers: [{ actifs: string }] = await usagerRepository.query(` SELECT COUNT(DISTINCT uh."usagerUUID") + COALESCE(SUM(jsonb_array_length(state->'ayantsDroits')), 0) AS "actifs" FROM "usager_history" uh JOIN usager u ON uh."usagerUUID" = u.uuid JOIN jsonb_array_elements(uh.states) AS state ON true @@ -138,7 +138,7 @@ async function countTotalActifs(): Promise { AND (state->>'historyEndDate' is null OR (state->>'historyEndDate')::timestamptz >= CURRENT_DATE + INTERVAL '1 day' ) `); - return usagers[0].actifs; + return parseInt(usagers[0].actifs, 10); } async function countMigratedUsagers(): Promise { diff --git a/packages/backend/src/stats/controllers/stats.public.controller.spec.ts b/packages/backend/src/stats/controllers/stats.public.controller.spec.ts index 9715faa564..f6eb163c4b 100644 --- a/packages/backend/src/stats/controllers/stats.public.controller.spec.ts +++ b/packages/backend/src/stats/controllers/stats.public.controller.spec.ts @@ -11,9 +11,11 @@ import { JEST_FAKE_TIMER, } from "../../util/test"; import { AdminStructuresModule } from "../../_portail-admin/admin-structures/admin-structures.module"; -import { StatsPublicController } from "./StatsPublicController"; import { domifaConfig } from "../../config"; import { HomeStats, PublicStats } from "@domifa/common"; +import { StatsPublicController } from "./stats.public.controller"; +import { CacheModule } from "@nestjs/cache-manager"; +import { PublicStatsService } from "../services/publicStats.service"; describe("Stats Public Controller", () => { let controller: StatsPublicController; @@ -34,214 +36,220 @@ describe("Stats Public Controller", () => { context = await AppTestHelper.bootstrapTestApp({ controllers: [StatsPublicController], imports: [ + CacheModule.register(), forwardRef(() => AdminStructuresModule), forwardRef(() => UsersModule), forwardRef(() => StructuresModule), forwardRef(() => UsagersModule), forwardRef(() => InteractionsModule), ], - providers: [], + providers: [PublicStatsService], }); controller = context.module.get( StatsPublicController ); }); - it("Stats HomePage", async () => { - const response = await supertest(context.app.getHttpServer()).get( - "/stats/home" - ); - - expect(response.status).toBe(HttpStatus.OK); - - const content = response.body as HomeStats; - expect(content.interactions).toEqual(5); - expect(content.structures).toEqual(5); - expect(content.usagers).toEqual(20); + it("should be defined", () => { + expect(controller).toBeDefined(); }); - it("Stats Page : national", async () => { - const response = await supertest(context.app.getHttpServer()).get( - "/stats/public-stats" - ); + describe("Homepage", () => { + it("Stats HomePage", async () => { + const response = await supertest(context.app.getHttpServer()).get( + "/stats/home" + ); - const retour: PublicStats = { - usagersCount: 20, - usersCount: 10, - structuresCount: 5, - courrierInCount: 5, - courrierOutCount: 2, - structuresCountByRegion: [ - { count: 2, region: "52" }, - { count: 1, region: "03" }, - { count: 1, region: "11" }, - { count: 1, region: "75" }, - ], - structuresCountByTypeMap: { asso: 2, cias: 2, ccas: 1, mairie: 0 }, - interactionsCountByMonth: [ - { name: "août", value: 0 }, - { name: "sept.", value: 0 }, - { name: "oct.", value: 0 }, - { name: "nov.", value: 0 }, - { name: "déc.", value: 0 }, - { name: "janv.", value: 0 }, - { name: "févr.", value: 0 }, - { name: "mars", value: 0 }, - { name: "avr.", value: 0 }, - { name: "mai", value: 0 }, - { name: "juin", value: 0 }, - { name: "juil.", value: 0 }, - ], - usagersCountByMonth: [ - { name: "août", value: 0 }, - { name: "sept.", value: 0 }, - { name: "oct.", value: 0 }, - { name: "nov.", value: 4 }, - { name: "déc.", value: 0 }, - { name: "janv.", value: 0 }, - { name: "févr.", value: 0 }, - { name: "mars", value: 1 }, - { name: "avr.", value: 0 }, - { name: "mai", value: 0 }, - { name: "juin", value: 0 }, - { name: "juil.", value: 0 }, - ], - }; + expect(response.status).toBe(HttpStatus.OK); - expect(response.status).toBe(HttpStatus.OK); - expect(response.body).toEqual(retour); + const content = response.body as HomeStats; + expect(content.interactions).toEqual(5); + expect(content.structures).toEqual(5); + expect(content.usagers).toEqual(20); + expect(content.actifs).toEqual(11); + }); }); - it("Statistiques régionales : Pays de la Loire", async () => { - const response = await supertest(context.app.getHttpServer()).get( - "/stats/public-stats/52" - ); - - const retour: PublicStats = { - usagersCount: 0, - usersCount: 5, - structuresCount: 2, - courrierInCount: 0, - courrierOutCount: 0, - structuresCountByRegion: [ - { - count: 2, - region: "44", - }, - ], - structuresCountByTypeMap: { - asso: 2, - cias: 0, - ccas: 0, - mairie: 0, - }, - interactionsCountByMonth: [ - { - name: "août", - value: 0, - }, - { - name: "sept.", - value: 0, - }, - { - name: "oct.", - value: 0, - }, - { - name: "nov.", - value: 0, - }, - { - name: "déc.", - value: 0, - }, - { - name: "janv.", - value: 0, - }, - { - name: "févr.", - value: 0, - }, - { - name: "mars", - value: 0, - }, - { - name: "avr.", - value: 0, - }, - { - name: "mai", - value: 0, - }, - { - name: "juin", - value: 0, - }, - { - name: "juil.", - value: 0, - }, - ], - usagersCountByMonth: [ - { - name: "août", - value: 0, - }, - { - name: "sept.", - value: 0, - }, - { - name: "oct.", - value: 0, - }, - { - name: "nov.", - value: 0, - }, - { - name: "déc.", - value: 0, - }, - { - name: "janv.", - value: 0, - }, - { - name: "févr.", - value: 0, - }, - { - name: "mars", - value: 0, - }, - { - name: "avr.", - value: 0, - }, - { - name: "mai", - value: 0, - }, - { - name: "juin", - value: 0, - }, - { - name: "juil.", - value: 0, - }, - ], - }; - - expect(response.status).toBe(HttpStatus.OK); - expect(response.body).toEqual(retour); - }); + describe("National page", () => { + it("Should display stats for France", async () => { + const response = await supertest(context.app.getHttpServer()).get( + "/stats/public-stats" + ); + + const retour: PublicStats = { + usagersCount: 20, + usersCount: 10, + structuresCount: 5, + courrierInCount: 5, + courrierOutCount: 2, + structuresCountByRegion: [ + { count: 2, region: "52" }, + { count: 1, region: "03" }, + { count: 1, region: "11" }, + { count: 1, region: "75" }, + ], + structuresCountByTypeMap: { asso: 2, cias: 2, ccas: 1, mairie: 0 }, + interactionsCountByMonth: [ + { name: "août", value: 0 }, + { name: "sept.", value: 0 }, + { name: "oct.", value: 0 }, + { name: "nov.", value: 0 }, + { name: "déc.", value: 0 }, + { name: "janv.", value: 0 }, + { name: "févr.", value: 0 }, + { name: "mars", value: 0 }, + { name: "avr.", value: 0 }, + { name: "mai", value: 0 }, + { name: "juin", value: 0 }, + { name: "juil.", value: 0 }, + ], + usagersCountByMonth: [ + { name: "août", value: 0 }, + { name: "sept.", value: 0 }, + { name: "oct.", value: 0 }, + { name: "nov.", value: 4 }, + { name: "déc.", value: 0 }, + { name: "janv.", value: 0 }, + { name: "févr.", value: 0 }, + { name: "mars", value: 1 }, + { name: "avr.", value: 0 }, + { name: "mai", value: 0 }, + { name: "juin", value: 0 }, + { name: "juil.", value: 0 }, + ], + }; + + expect(response.status).toBe(HttpStatus.OK); + expect(response.body).toEqual(retour); + }); - it("should be defined", () => { - expect(controller).toBeDefined(); + it("Should display stats for 'Pays de la Loire'", async () => { + const response = await supertest(context.app.getHttpServer()).get( + "/stats/public-stats/52" + ); + + const retour: PublicStats = { + usagersCount: 0, + usersCount: 5, + structuresCount: 2, + courrierInCount: 0, + courrierOutCount: 0, + structuresCountByRegion: [ + { + count: 2, + region: "44", + }, + ], + structuresCountByTypeMap: { + asso: 2, + cias: 0, + ccas: 0, + mairie: 0, + }, + interactionsCountByMonth: [ + { + name: "août", + value: 0, + }, + { + name: "sept.", + value: 0, + }, + { + name: "oct.", + value: 0, + }, + { + name: "nov.", + value: 0, + }, + { + name: "déc.", + value: 0, + }, + { + name: "janv.", + value: 0, + }, + { + name: "févr.", + value: 0, + }, + { + name: "mars", + value: 0, + }, + { + name: "avr.", + value: 0, + }, + { + name: "mai", + value: 0, + }, + { + name: "juin", + value: 0, + }, + { + name: "juil.", + value: 0, + }, + ], + usagersCountByMonth: [ + { + name: "août", + value: 0, + }, + { + name: "sept.", + value: 0, + }, + { + name: "oct.", + value: 0, + }, + { + name: "nov.", + value: 0, + }, + { + name: "déc.", + value: 0, + }, + { + name: "janv.", + value: 0, + }, + { + name: "févr.", + value: 0, + }, + { + name: "mars", + value: 0, + }, + { + name: "avr.", + value: 0, + }, + { + name: "mai", + value: 0, + }, + { + name: "juin", + value: 0, + }, + { + name: "juil.", + value: 0, + }, + ], + }; + + expect(response.status).toBe(HttpStatus.OK); + expect(response.body).toEqual(retour); + }); }); }); diff --git a/packages/backend/src/stats/controllers/stats.public.controller.ts b/packages/backend/src/stats/controllers/stats.public.controller.ts index 12e36ea2c2..fb4ce68f50 100644 --- a/packages/backend/src/stats/controllers/stats.public.controller.ts +++ b/packages/backend/src/stats/controllers/stats.public.controller.ts @@ -15,13 +15,16 @@ export class StatsPublicController { @Get("home") public async home(): Promise { - return this.publicStatsService.generateHomeStats(); + return this.publicStatsService.generateHomeStats({ updateCache: false }); } @Get("public-stats/:regionId?") public async getPublicStats( @Param("regionId", new ParseRegionPipe()) regionId: FranceRegion ): Promise { - return this.publicStatsService.generatePublicStats(regionId); + return this.publicStatsService.generatePublicStats({ + updateCache: false, + regionId, + }); } } diff --git a/packages/backend/src/stats/services/publicStats.service.ts b/packages/backend/src/stats/services/publicStats.service.ts index ea0adfbc7a..c92b9db7b2 100644 --- a/packages/backend/src/stats/services/publicStats.service.ts +++ b/packages/backend/src/stats/services/publicStats.service.ts @@ -24,7 +24,11 @@ export class PublicStatsService implements OnModuleInit { onModuleInit() { // Inutile de rafraichir le cache sur le pod des tâches CRON - if (domifaConfig().envId !== "local" && !isCronEnabled()) { + if ( + domifaConfig().envId !== "local" && + domifaConfig().envId !== "test" && + !isCronEnabled() + ) { this.updateAllStatsCache(); } } @@ -35,25 +39,29 @@ export class PublicStatsService implements OnModuleInit { }) public async updateAllStatsCache(): Promise { appLogger.info("[CACHE] Update home stats"); - await this.generateHomeStats(); + await this.generateHomeStats({ updateCache: true }); appLogger.info("[CACHE] Update public stats"); - await this.generatePublicStats(); + await this.generatePublicStats({ updateCache: true }); for (const regionId of FRANCE_REGION_CODES) { appLogger.info("[CACHE] Update public stats for region " + regionId); - await this.generatePublicStats(regionId); + await this.generatePublicStats({ updateCache: true, regionId }); } appLogger.info("[CACHE] End of cache update"); } - public async generateHomeStats(): Promise { + public async generateHomeStats({ + updateCache, + }: { + updateCache: boolean; + }): Promise { const value: HomeStats | undefined = await this.cacheManager.get( "home-stats" ); - if (value) { + if (value && !updateCache) { return value; } @@ -71,13 +79,17 @@ export class PublicStatsService implements OnModuleInit { return homeStats; } - public async generatePublicStats( - regionId?: FranceRegion - ): Promise { + public async generatePublicStats({ + updateCache, + regionId, + }: { + updateCache?: boolean; + regionId?: FranceRegion; + }): Promise { const key = regionId ? "publics-stats-" + regionId : "public-stats"; const value: PublicStats | undefined = await this.cacheManager.get(key); - if (value) { + if (value && !updateCache) { return value; } diff --git a/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts b/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts index 82238a67f2..5a43d99c5d 100644 --- a/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts +++ b/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts @@ -274,7 +274,7 @@ function buildHistoryState({ etapeDemande: usager.etapeDemande, entretien, ayantsDroits, - rdv: { dateRdv: usager?.rdv.dateRdv }, + rdv: { dateRdv: usager?.rdv?.dateRdv }, }; return state;