@mostajs/scheduler
v0.2.0
Published
Déclencher une action à échéance : daily/weekly/monthly/count. Franchissement de frontière (idempotent), planification relue à chaud, adoption de la période au démarrage. Primitive N0, zéro dépendance. Extrait de @mostajs/queue.
Maintainers
Readme
@mostajs/scheduler
Auteur : Dr Hamid MADANI [email protected] · Licence : AGPL-3.0-or-later Niveau : N0 · Zéro dépendance
Déclencher une action à échéance. Rien d'autre.
daily · weekly · monthly · count · never
Pourquoi ce module existe
Cette mécanique vivait dans @mostajs/queue sous le nom createResetScheduler. Elle y était
déjà générique — mais son vocabulaire était prisonnier du domaine : ResetMode,
reset(), un seuil compté en tickets. Aucun autre module ne pouvait s'en servir sans
« réinitialiser des compteurs ». Or @mostajs/backup a besoin exactement de cette mécanique.
L'extraction ne change rien au fonctionnement : elle neutralise les noms. @mostajs/queue
conserve createResetScheduler comme enveloppe — aucune rupture.
Les trois pièges qu'il évite
Le double déclenchement. On ne compare pas des durées écoulées (fragile aux dérives d'horloge et aux redémarrages) : on compare la dernière frontière franchie à celle déjà traitée. Une frontière ne déclenche qu'une fois, quel que soit le nombre de ticks.
Le déclenchement au démarrage. Le planificateur adopte la période courante sans rien lancer — sinon tout redémarrage relancerait une sauvegarde, et un serveur qui redémarre souvent en lancerait indéfiniment. Corollaire assumé : un serveur éteint une semaine ne rattrape pas les sept frontières manquées — sept sauvegardes d'affilée seraient pires que six manquées.
Le planificateur mort en silence. Sans onError, l'erreur d'un tick est avalée : il a
l'air vivant, mais ne déclenche plus rien. On ne le découvre qu'en cherchant la sauvegarde qui
n'existe pas.
Usage
import { createScheduler } from '@mostajs/scheduler';
const s = createScheduler({
getSchedule: () => config.backup, // RELUE à chaque tick → changement à chaud
onTrigger: (now) => createBackup(...),
onError: (e) => logger.error(e), // sans ça, la panne est silencieuse
});
s.start();monthly avec dayOfMonth: 31 est borné à la fin du mois : sans ce bornage, la planification
ne se déclencherait jamais en février, avril, juin, septembre ni novembre — et la panne serait
invisible pendant des mois.
Ce que ce module n'est PAS
Un moteur de récurrence. Il déclenche ; il ne sait pas énumérer les occurrences d'une règle complexe (« le 2e mardi de chaque mois »).
L'écosystème a déjà trois vocabulaires du temps : ce planificateur (déclencher),
@mostajs/booking (étendre en créneaux), et @mostajs/booking-rrule (RRULE RFC 5545 —
placeholder, aucun code). Déclencher et étendre ne sont pas la même mécanique : on ne les
fusionne pas.
Schedule est laissé extensible pour accueillir un jour { mode: 'rrule', rrule: '…' }. On
ne construit pas RRULE aujourd'hui : aucun consommateur réel ne le réclame. Le jour où l'un
prend vie, on extraira @mostajs/recurrence, consommé par ce module et par booking.
Tests
npm test # 16 tests mjs-unitUn planificateur ne se teste pas en attendant : l'horloge est injectée. On fait avancer le temps à la main, et on vérifie surtout ce qui ne se déclenche pas.
