From cfe9b6ada8b39115c21af27ccdf81994c5a52aac Mon Sep 17 00:00:00 2001 From: Paul Gaucher Date: Mon, 16 Dec 2024 12:37:57 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20mise=20=C3=A0=20jour=20du=20scipt=20de?= =?UTF-8?q?=20mise=20a=20jour=20des=20computed=20effectif?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actions/effectifs.statut.actions.ts | 1 + .../hydrate-effectifs-computed-types.ts | 48 +++++++++++++++---- server/src/jobs/jobs.ts | 26 +++++----- shared/utils/date.ts | 4 ++ 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/server/src/common/actions/effectifs.statut.actions.ts b/server/src/common/actions/effectifs.statut.actions.ts index 7f93ea2f4..7e4debb67 100644 --- a/server/src/common/actions/effectifs.statut.actions.ts +++ b/server/src/common/actions/effectifs.statut.actions.ts @@ -74,6 +74,7 @@ export function createComputedStatutObject( function createUpdateObject(effectif: IEffectif, evaluationDate: Date): UpdateFilter { return { $set: { + updated_at: new Date(), "_computed.statut": createComputedStatutObject(effectif, evaluationDate), }, }; diff --git a/server/src/jobs/hydrate/effectifs/hydrate-effectifs-computed-types.ts b/server/src/jobs/hydrate/effectifs/hydrate-effectifs-computed-types.ts index 1d8570085..9872cb3eb 100644 --- a/server/src/jobs/hydrate/effectifs/hydrate-effectifs-computed-types.ts +++ b/server/src/jobs/hydrate/effectifs/hydrate-effectifs-computed-types.ts @@ -1,4 +1,6 @@ import { captureException } from "@sentry/node"; +import { IEffectif } from "shared/models"; +import { substractDaysUTC } from "shared/utils"; import { updateEffectifStatut } from "@/common/actions/effectifs.statut.actions"; import logger from "@/common/logger"; @@ -11,26 +13,54 @@ import { effectifsDb } from "@/common/model/collections"; * query (Requête MongoDB pour filtrer les effectifs) et * evaluationDate (La date pour évaluer le statut des effectifs). */ -export async function hydrateEffectifsComputedTypes({ query = {}, evaluationDate = new Date() } = {}) { +export async function hydrateEffectifsComputedTypes( + { query = {}, evaluationDate = new Date() } = {}, + signal: AbortSignal +) { let nbEffectifsMisAJour = 0; let nbEffectifsNonMisAJour = 0; + const BULK_SIZE = 100; + let bulkEffectifs: IEffectif[] = []; + + const computedQuery = { + ...query, + updated_at: { $lt: substractDaysUTC(evaluationDate, 7) }, + }; + + const processEffectif = async (eff: IEffectif) => { + if (eff) { + const isSuccess = await updateEffectifStatut(eff, evaluationDate); + if (isSuccess) { + nbEffectifsMisAJour++; + } else { + nbEffectifsNonMisAJour++; + } + } + }; + try { - const cursor = effectifsDb().find(query); + const cursor = effectifsDb().find(computedQuery); while (await cursor.hasNext()) { - const effectif = await cursor.next(); - + const effectif: IEffectif | null = await cursor.next(); if (effectif) { - const isSuccess = await updateEffectifStatut(effectif, evaluationDate); - if (isSuccess) { - nbEffectifsMisAJour++; - } else { - nbEffectifsNonMisAJour++; + bulkEffectifs.push(effectif); + } + + if (bulkEffectifs.length > BULK_SIZE) { + await Promise.allSettled(bulkEffectifs.map(processEffectif)); + if (signal && signal.aborted) { + return; } + bulkEffectifs = []; } } + if (bulkEffectifs.length > 0) { + await Promise.allSettled(bulkEffectifs.map(processEffectif)); + } + logger.info(`${nbEffectifsMisAJour} effectifs mis à jour, ${nbEffectifsNonMisAJour} effectifs non mis à jour.`); } catch (err) { logger.error(`Échec de la mise à jour des effectifs: ${err}`); diff --git a/server/src/jobs/jobs.ts b/server/src/jobs/jobs.ts index c5b852627..466faff03 100644 --- a/server/src/jobs/jobs.ts +++ b/server/src/jobs/jobs.ts @@ -118,10 +118,10 @@ export async function setupJobProcessor() { }, }, - "Mettre à jour les statuts d'effectifs le 1er de chaque mois à 00h45": { - cron_string: "45 0 1 * *", + "Mettre à jour les statuts d'effectifs tous les samedis matin à 5h": { + cron_string: "0 5 * * 6", handler: async () => { - await addJob({ name: "hydrate:effectifs:update_computed_statut_month", queued: true }); + await addJob({ name: "hydrate:effectifs:update_computed_statut", queued: true }); return 0; }, }, @@ -183,16 +183,20 @@ export async function setupJobProcessor() { return hydrateDecaRaw(); }, }, - "hydrate:effectifs:update_computed_statut_month": { - handler: async (job?) => { - const organismeId = (job?.payload?.id as string) ? new ObjectId(job?.payload?.id as string) : null; - return hydrateEffectifsComputedTypes({ - query: { - annee_scolaire: { $in: getAnneesScolaireListFromDate(new Date()) }, - ...(organismeId ? { organisme_id: organismeId } : {}), + "hydrate:effectifs:update_computed_statut": { + handler: async (job, signal) => { + const organismeId = (job.payload?.id as string) ? new ObjectId(job.payload?.id as string) : null; + return hydrateEffectifsComputedTypes( + { + query: { + annee_scolaire: { $in: getAnneesScolaireListFromDate(new Date()) }, + ...(organismeId ? { organisme_id: organismeId } : {}), + }, }, - }); + signal + ); }, + resumable: true, }, "hydrate:effectifs-formation-niveaux": { handler: async () => { diff --git a/shared/utils/date.ts b/shared/utils/date.ts index b0a817e1f..95c6748c5 100644 --- a/shared/utils/date.ts +++ b/shared/utils/date.ts @@ -3,6 +3,10 @@ export function addDaysUTC(date: Date, days: number) { return result; } +export function substractDaysUTC(date: Date, days: number) { + return addDaysUTC(date, -days); +} + export const getYearFromDate = (date?: Date | null): number | undefined => { return date ? new Date(date).getFullYear() : undefined; };