From 42f8e63aa985c10578bfe3a5c6bdadc4e4a28502 Mon Sep 17 00:00:00 2001 From: "Paul G." Date: Mon, 16 Dec 2024 14:46:03 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20mise=20=C3=A0=20jour=20du=20scipt=20de?= =?UTF-8?q?=20mise=20a=20jour=20des=20computed=20effectif=20(#3941)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Paul Gaucher --- server/src/commands.ts | 2 +- .../actions/effectifs.statut.actions.ts | 1 + .../hydrate-effectifs-computed-types.ts | 40 +++++++++++++++---- server/src/jobs/jobs.ts | 30 ++++++++------ shared/utils/date.ts | 4 ++ 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/server/src/commands.ts b/server/src/commands.ts index 28ee342a4..328bb0bd5 100644 --- a/server/src/commands.ts +++ b/server/src/commands.ts @@ -306,7 +306,7 @@ program .description("Manually trigger the update of the computed") .option("--id ", "Id de l'organisme", (organismeId) => organismeId, null) .option("-q, --queued", "Run job asynchronously", false) - .action(createJobAction("hydrate:effectifs:update_computed_statut_month")); + .action(createJobAction("hydrate:effectifs:update_computed_statut")); program .command("job:run") 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..be463b392 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,5 @@ import { captureException } from "@sentry/node"; +import { IEffectif } from "shared/models"; import { updateEffectifStatut } from "@/common/actions/effectifs.statut.actions"; import logger from "@/common/logger"; @@ -11,26 +12,49 @@ 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 processEffectif = async (eff: IEffectif) => { + if (eff) { + const isSuccess = await updateEffectifStatut(eff, evaluationDate); + if (isSuccess) { + nbEffectifsMisAJour++; + } else { + nbEffectifsNonMisAJour++; + } + } + }; + try { const cursor = effectifsDb().find(query); 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..906fa956f 100644 --- a/server/src/jobs/jobs.ts +++ b/server/src/jobs/jobs.ts @@ -2,7 +2,7 @@ import { addJob, initJobProcessor } from "job-processor"; import { MongoError, ObjectId, WithId } from "mongodb"; import { MOTIF_SUPPRESSION } from "shared/constants"; import type { IEffectif } from "shared/models"; -import { getAnneesScolaireListFromDate } from "shared/utils"; +import { getAnneesScolaireListFromDate, substractDaysUTC } from "shared/utils"; import { softDeleteEffectif } from "@/common/actions/effectifs.actions"; import logger from "@/common/logger"; @@ -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,22 @@ 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; + const evaluationDate = new Date(); + return hydrateEffectifsComputedTypes( + { + query: { + annee_scolaire: { $in: getAnneesScolaireListFromDate(evaluationDate) }, + updated_at: { $lt: substractDaysUTC(evaluationDate, 7) }, + ...(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; };