feat(scheduler): automatisations planifiées (cron) — tâche 5

- table schedules (migration 0007) + service scheduler (croner) : CRUD,
  runSchedule avec scope (all/liste), pool de concurrence et verrou par machine,
  mapping actions → refresh/metrics/docker_scan ; reloadSchedules au boot
- worker = reloadSchedules (remplace le refresh 30 min en dur)
- routes /api/schedules (CRUD + :id/run) ; cron invalide rejeté (validation croner)
- UI Paramètres : onglet « Automatisations » (liste, activer/lancer/supprimer, création)

tsc 0 · 113 tests · build OK · boot OK (migration 0007, CRUD vérifié).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 19:25:44 +02:00
parent bdbe7af55c
commit ff9cfaa9e1
11 changed files with 2796 additions and 18 deletions
@@ -0,0 +1,35 @@
# Tâche 5 — Automatisations planifiées (scheduler croner)
> Statut : **implémenté** (2026-06-06). tsc 0 · 113 tests · build OK · boot OK.
> Réf. : `tache5.md §4` (automatisations backend), `validation_tache5.md`.
## Périmètre livré (1re tranche tâche 5)
Planificateur piloté par la BDD : exécuter `apt_update_analyze` / `machine_metrics_simple` /
`docker_scan` sur un périmètre de machines à heure fixe (cron), avec concurrence + verrou.
- **Table `schedules`** (migration 0007) : name, enabled, cron, timezone, scope_json,
actions_json, concurrency, notify_on_json, last_run_at, last_status.
- **`server/services/scheduler.ts`** :
- CRUD (validation cron via `new Cron()` à la création/maj).
- `runSchedule` : résout le scope (`all` ou liste), exécute les actions par machine avec
**pool de concurrence** + **verrou par machine** (in-process Set, évite 2 actions
simultanées), met à jour last_run_at/last_status, `recordEvent` sur échec.
- mapping actions → `refreshMachine` / `collectMetrics` / `scanDockerStacks`.
- `reloadSchedules` : (ré)enregistre les crons actifs via croner (timezone par schedule).
- **`worker.ts`** : `startWorker` = `reloadSchedules()` (remplace le refresh 30 min en dur).
- **Routes** `/api/schedules` : list / create / get / patch / delete / `:id/run` (lancement immédiat).
- **UI** : onglet Paramètres « Automatisations » — liste (cron, actions, actif, dernier run),
activer/désactiver, lancer maintenant, supprimer, et formulaire de création (nom, cron,
cases d'actions, toutes machines).
## Vérifié
CRUD via API, cron invalide rejeté proprement (message croner), init scheduler sans erreur,
migration 0007 appliquée. Verrou empêche les exécutions concurrentes sur une même machine.
## Reste tâche 5 (backlog)
Notifications (`notifyOn`), tags de scope, retries persistants, extraction structurée des
**messages importants** (E:/W:/dépréciations → `important_messages` + tuile), timeline
d'événements machine, politiques de rétention. (pg-boss = piste future si jobs distribués.)