J6 — Le solveur
Vérifié contre le produit le .
L’objectif du jour : lancer un solve en local, lire son résultat, et savoir ce qui se passe entre le clic et la suggestion.
| Durée réaliste | une demi-journée, plus si vous touchez au Kotlin |
| Prérequis | J1 (le conteneur du solveur tourne) et J2 (des données à optimiser) |
| JDK | seulement si vous construisez le solveur en local — voir le piège du jour |
Ce que le solveur est, et n’est pas
Section intitulée « Ce que le solveur est, et n’est pas »Un service JVM en Kotlin, servi par Quarkus, qui embarque Timefold. Il résout le placement d’un lot de séances sous les contraintes du catalogue, là où le scoreur TypeScript de l’API répond instantanément sur un cours.
Trois propriétés qui expliquent tout le reste :
- Il n’a aucun accès aux données. Le problème arrive complet dans la requête — le snapshot. Impossible de respecter le RLS proprement depuis la JVM, donc la JVM ne parle pas à la base.
- Il est sans état entre deux solves. Rien à purger, rien à migrer, il redémarre à froid sans conséquence.
- Il ne décide de rien. Il propose ; l’API et l’humain disposent.
Le contrat, tenu des deux côtés
Section intitulée « Le contrat, tenu des deux côtés »C’est la particularité du module : son contrat existe deux fois, et les deux doivent rester d’accord.
| Où | Quoi |
|---|---|
packages/schemas/src/solver.ts |
les schémas Zod du problème et de la solution, côté TypeScript |
apps/solver/.../api/SolverDtos.kt |
les DTO Kotlin miroirs |
packages/constraints-fixtures |
des scénarios JSON purs que les deux moteurs de scoring doivent évaluer à l’identique |
Toute évolution touche les deux côtés dans le même changement. Et l’équivalence se prouve :
bun run test:contract # côté API et côté solveurAucun job de CI ne joue cette commande — si vous touchez à une contrainte ou au contrat, elle n’existe que si vous la lancez.
Comment un solve se déroule
Section intitulée « Comment un solve se déroule »- L’API constitue le snapshot : le problème complet, le profil de contraintes avec ses poids, la configuration du calcul.
- Elle poste le tout au solveur, qui répond immédiatement un identifiant de job — le calcul, lui, dure des minutes.
- Le solveur commence par un warm start glouton La première solution grossière, construite en quelques millisecondes, que le calcul améliore ensuite plutôt que de partir de rien. : un placement heuristique déterministe qui pose toutes les séances sans violer les contraintes dures, en quelques millisecondes. La construction par défaut de Timefold n’y arriverait pas dans le budget. Ensuite seulement démarre la recherche locale, qui améliore.
- L’API suit l’avancement et récupère la meilleure solution courante.
- À l’application, elle vérifie l’époque de planification : si quelqu’un a bougé quelque chose dans le périmètre du solve pendant le calcul, le résultat est refusé plutôt qu’appliqué par-dessus. Un solve de plusieurs minutes n’écrase jamais le travail d’un humain en silence.
Les deux documents qui font foi : docs/solver.md pour le moteur, docs/solve-orchestration.md
pour l’orchestration et l’époque.
Lancer un solve en local
Section intitulée « Lancer un solve en local »Le service tourne depuis J1 (docker compose up -d). Vérifiez-le d’abord :
curl http://localhost:8082/q/health/readyPuis passez par le produit plutôt que par curl : sur un tenant peuplé, le panneau
« Placement optimisé » de la grille compose un vrai snapshot pour vous. C’est la façon la plus
rapide de voir un solve complet, et le chemin de 2 heures en fait
son quatrième bloc.
Les limites d’exploitation, à connaître avant de s’étonner :
- un solve actif à la fois par établissement, et un plafond global — un refus explicite plutôt qu’une file d’attente ;
- une durée plafonnée par requête ;
- des jobs évincés après une trentaine de minutes.
Le piège du jour
Section intitulée « Le piège du jour »Ce qui doit exister à la fin de la journée
Section intitulée « Ce qui doit exister à la fin de la journée »- La sonde du solveur répond
- Vous avez lancé un solve depuis le panneau « Placement optimisé » et lu sa suggestion
- Vous savez pourquoi le solveur n’accède pas à la base
- Vous savez où vit le contrat, des deux côtés, et comment prouver leur équivalence
- Vous savez ce qu’est le warm start glouton et pourquoi il existe
- Vous savez ce que l’époque de planification protège
J7 — Contribuer : les vérifications, la CI et ses quatre pièges, les conventions — et une première contribution qui passe le pipeline.