La façade sert /api/start, /api/stop, /api/restart, /api/vram/unload et /api/vram/reload quand LOKI_ENGINE=rust (expérimental ; le Go reste le défaut). Elle lance elle-même « loki-rs engine <action> », le superviseur que le Go appelait déjà en conteneur, avec l'environnement qu'il lui passait et de quoi joindre l'API interne du Go ; sa dernière ligne d'erreur devient l'erreur rendue. Le contrôle d'avant démarrage (preflightEngine : preset externe, Strata, BIN, MODEL, tranches) et le bilan de VRAM du déchargement (gpuSettle) sont portés. La façade ne tient ce lot qu'en conteneur : sous systemd ou avec LOKI_ENGINE_SUPERVISOR=go, loki-rs ne passe pas la variable au Go. Restent au Go derrière son API interne (facade_engine.go) : le verrou de l'optimiseur avant tout démarrage (/internal/v1/service/prestart), la réponse en cours quand il tient la conversation (/internal/v1/chat/generating) et l'arrêt de la dictée quand il la tient (/internal/v1/dictate/stop). Parité : parity_engine_test.go tire du Go dix bilans de VRAM, vingt-six installations passées au préflight, les messages du superviseur et dix réponses de route, rejoués par tests/enginectl.rs ; démarrage, arrêt, redémarrage, déchargement chiffré et rechargement vérifiés de bout en bout avec un faux superviseur et un faux nvidia-smi ; TestFacadeMoteur côté Go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
4.2 KiB
Lot 16 — pilotage du moteur tenu par la façade
Contexte
Le Go pilotait le moteur depuis l'interface :
svcHandler(web_api.go) pour/api/start,/api/stopet/api/restart;handleVramUnloadethandleVramReload(web_vram.go) pour rendre la carte graphique à la machine, puis la reprendre ;serviceAction(sys_service.go) : le verrou de l'optimiseur, puis, en conteneur, le superviseur Rustloki-rs engine <action>(lot 3,sys_service_rust_linux.go) ;preflightEngine: ce sans quoi le moteur ne peut pas démarrer, dit avant de le lancer.
Lot 16 : la façade tient ces routes quand LOKI_ENGINE=rust
(enginectl.rs, expérimental). Sans la variable, rien ne change.
| Route | Rôle |
|---|---|
/api/start, /api/stop, /api/restart |
pilotage du moteur ; réponse {ok, out} comme le Go |
POST /api/vram/unload |
arrête le moteur et la dictée, rapporte la VRAM rendue ; refusé pendant une réponse en cours sauf {force: true} |
POST /api/vram/reload |
relance le moteur après le contrôle d'avant démarrage ; {already: true} s'il tourne |
La façade lance elle-même loki-rs engine <action>, avec l'environnement que
le Go lui passait (LOKI_GO_BIN, LOKI_HOME, LOKI_SERVICE) et de quoi
joindre l'API interne du Go pour loki-rs engine serve (LOKI_GO_ADDR,
LOKI_INTERNAL_TOKEN). Sa dernière ligne d'erreur devient l'erreur rendue,
sans le préfixe du binaire. Un preset externe ne lance rien ; un redémarrage
arrête alors le moteur local.
Le bilan de VRAM suit gpuSettle :
- une lecture ratée est sautée, jamais comptée « 0 Mo » ;
- un palier ne conclut qu'une fois la baisse commencée ;
- les jauges du moniteur sont invalidées après coup.
Quand la façade ne tient pas ce lot
La façade ne prend ce lot qu'en conteneur, avec son superviseur. Sous
systemd, ou avec LOKI_ENGINE_SUPERVISOR=go, loki-rs ne passe pas
LOKI_ENGINE au Go, qui garde les routes (décidé au démarrage, raison dans
le journal).
Restent au Go
Le Go expose trois routes internes (facade_engine.go) :
POST /internal/v1/service/prestart: avant tout démarrage, refus pendant une optimisation, puis ménage d'un verrou périmé (essai orphelin arrêté, application interrompue défaite). Le verrou de l'optimiseur suit le processus qui le tient, il reste au Go jusqu'au lot de l'optimiseur ;GET /internal/v1/chat/generating: la réponse en cours, quand le Go tient la conversation (sinon la façade lit la sienne) ;POST /internal/v1/dictate/stop: l'arrêt de la dictée, quand le Go la tient (sinon la façade arrête la sienne).
GET /internal/v1/tune/guard (lot 15) sert le refus 409 du rechargement.
Les autres appelants de serviceAction côté Go (bascule de preset,
optimiseur, mises à jour du moteur) passent toujours par le Go. Les deux voies
lancent le même superviseur, sur les mêmes fichiers PID et journal.
Écarts assumés
engineNeedsStopregarde aussi les états transitoires de systemd. En conteneur, seul cas où la façade tient ce lot, il se réduit au PID vivant.- Un superviseur tué par un signal est décrit comme par le Go (« signal: killed ») pour les signaux courants, par son numéro sinon.
Parité
internal/loki/parity_engine_test.go tire du Go :
- dix bilans de VRAM (palier avant la baisse, lectures ratées, VRAM en hausse…) ;
- la dernière ligne d'erreur du superviseur et le retrait des couleurs ;
- vingt-six installations passées au contrôle d'avant démarrage (preset externe, Strata, BIN absent ou relatif, MODEL absent, hors des dossiers, remontant, en tranches incomplètes…) ;
- dix réponses de route qui ne lancent rien (GET refusé avec
Allow: POST, optimisation ou réponse en cours, moteur déjà arrêté, contrôle en échec).
tests/enginectl.rs rejoue le tout par la façade. Il vérifie aussi de bout en
bout, avec un faux superviseur et un faux nvidia-smi :
- démarrage, arrêt, redémarrage, refus pendant une optimisation ;
- échec du démarrage, preset externe ;
- déchargement chiffré, arrêt en échec, VRAM en hausse ;
- rechargement.
Une mutation de chaque règle fait échouer les tests.
Côté Go, TestFacadeMoteur vérifie le relais et les trois routes internes.