Définies dans api/src/core/cron-tasks/cron-tasks.ts. Toutes les tâches datées utilisent le fuseau Europe/Paris.

Tâches récurrentes (automatiques)

Méthode Schedule Description
monitorMuxAssets toutes les 2 secondes Surveille l'état des assets vidéo Mux et met à jour leur statut
updateElasticDatabase toutes les minutes Synchronisation incrémentale de l'index ElasticSearch
updateElasticDatabaseDaily chaque jour à minuit Synchronisation complète (force all) de l'index ElasticSearch
mailToNotifyNewMessage chaque jour à 19h Envoie un email aux éclaireurs ayant reçu un message non lu dans le chat
mailToNotifyAbsenceOfResponseFromEclaireur chaque jour à 20h Envoie un email aux lycéens dont l'éclaireur n'a pas répondu

Tâches annuelles (rentrée scolaire — planning étalé fin août / début septembre)

Les dates ci-dessous ont été décalées et espacées en 2026 (initialement toutes calées sur le 1er août) pour éviter que plusieurs migrations lourdes ne tournent le même jour et ne surchargent le serveur.

Méthode Schedule Description
progressNiveauxAnnuels (niveau-cron.service.ts) 27 août à 00h00 Passage annuel des niveaux lycéens (Seconde → Première → Terminale → En transition), voir docs/mvls/passage-de-niveau.md
resetIsProfileCompleteForNewSchoolYear 31 août à 00h00 Remet isProfileComplete à false pour tous les éclaireurs — ils doivent re-valider leur profil pour la nouvelle année
hideInactiveEclaireursForNewSchoolYear 1er septembre à 12h00 Passe en statut caché les éclaireurs visibles n'ayant aucun parcours sur les 2 dernières années scolaires ; désindexe ces profils d'ElasticSearch
notifyObsoleteAccountsAugust 1er septembre à 00h00 Envoie l'email final (Brevo) aux utilisateurs non-admin 27+ ans révolus
archiveObsoleteAccountsAugust 2 septembre à 00h00 Anonymise les comptes notifiés la veille

Attention à la convention de mois du cron : la lib cron (v2, utilisée par @nestjs/schedule) attend un mois 0-indexé (0 = janvier … 11 = décembre), et non la convention standard 1-12. Une expression comme 0 0 1 8 * déclenche donc le 1er septembre, pas le 1er août. Toujours vérifier avec new CronTime(expr, 'Europe/Paris').sendAt() avant de modifier une de ces tâches.

Tâches annuelles (archivage — 1er juillet)

Méthode Schedule Description
notifyObsoleteAccountsJuly 1er août à 00h00 Envoie un email d'avertissement (Brevo) aux utilisateurs non-admin ayant plus de 27 ans révolus ; aucune suppression à ce stade. Non modifiée lors du décalage de 2026 — son schedule (0 0 1 7 *) reste calé sur le même bug de mois 0-indexé qu'avant et déclenche donc en réalité le 1er août, pas le 1er juillet

Logique d'archivage des comptes obsolètes

  • Population ciblée : utilisateurs sans rôle Admin, dont la date de naissance est renseignée et dont l'âge est ≥ 27 ans révolus à la date de référence.
  • Avertissement (notifyObsoleteAccountsJuly) : email d'avertissement (BREVO_TEMPLATE_ARCHIVAGE_JUILLET). Paramètre envoyé : PRENOM.
  • Email final (notifyObsoleteAccountsAugust, 1er septembre) : email final (BREVO_TEMPLATE_ARCHIVAGE_AOUT), calculé sur les utilisateurs ayant eu 27 ans révolus au 1er juillet de l'année en cours. Paramètre envoyé : PRENOM.
  • Anonymisation (archiveObsoleteAccountsAugust, 2 septembre) : même pipeline que la suppression manuelle (UserService.delete) — champs personnels effacés, email brouillé, notification RabbitMQ, soft-delete — puis resynchronisation de l'index ElasticSearch. Ne traite que les comptes marqués notifiedObsoleteAugustAt (donc déjà notifiés la veille).
  • Idempotence : chaque envoi réussi marque le user via notifiedObsoleteJulyAt/notifiedObsoleteAugustAt (colonnes users). Un rejeu de la tâche (ex. après un 504 sur l'endpoint admin) ne renotifie que les users pas encore marqués — on peut relancer la tâche sans risque de doublon, et interroger ces colonnes pour savoir qui a été notifié.
  • Déclenchement admin non bloquant : notify-obsolete-accounts-july, notify-obsolete-accounts-august et archive-obsolete-accounts-august bouclent sur potentiellement beaucoup d'users (1 appel Brevo/anonymisation chacun) ; l'endpoint admin ne les attend plus (void) pour éviter un 504 gateway sur les grosses volumétries. La réponse {success: true} signifie juste que la tâche a démarré — suivre la progression via les logs ou les colonnes notifiedObsolete*At.

Simulation manuelle (admin)

Les tâches ci-dessus (hors monitorMuxAssets et updateElasticDatabase qui tournent en continu) peuvent être déclenchées manuellement depuis l'interface admin : Admin → Tâches planifiées.

Les endpoints correspondants : POST /cron-tasks-admin/run/:task avec les valeurs de :task :

  • update-elastic-daily
  • notify-absence-of-response
  • reset-profile-complete
  • hide-inactive-eclaireurs
  • notify-obsolete-accounts-july
  • notify-and-delete-obsolete-accounts-august