mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 19:59:56 +02:00
main a reçu en parallèle la télémétrie du tour tenu par la façade (/internal/v1/turn/perf), les tickets « en vol » du moteur et la conversation tenue par la façade par défaut (LOKI_CHAT=go pour revenir au Go). Le lot 29 faisait la même chose par /internal/v1/perf/record : un seul chemin est gardé, celui de main. - TurnHost::perf_record (main) remplace TurnHost::perf ; la nature est posée par l'hôte (verify pour la passe isolée seulement, main pour les corrections du builder, comme le Go). - Les résumés de compaction passent par le même point d'entrée, nature compact : chat/perf.rs ne garde que le relevé de la réponse entière (perfRecFromWire) et l'envoi. - La sonde du gabarit reste à la façade (lot 23) : /internal/v1/turn/perf ne la lance plus côté Go. - facade_perf.go retiré ; ses cas (perte, intercalé, alerte, preset externe, incomplète, GET) rejoignent web_internal_turnperf_test.go. - README : LOKI_CHAT défaut Rust, avec ce que les lots 19, 23, 29 et 30 y ajoutent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
65 lines
2.5 KiB
Go
65 lines
2.5 KiB
Go
package loki
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
// Télémétrie d'une complétion d'un tour tenu par la façade Rust
|
|
// (LOKI_CHAT=rust). La boucle Go range chaque complétion dans l'anneau de
|
|
// perf_log.go (perfRecord) : c'est lui qui nourrit /api/perf/summary et
|
|
// l'alerte « cache perdu » posée sur les stats finales d'une complétion. La
|
|
// boucle Rust lui envoie la même chose, ici, au même moment.
|
|
//
|
|
// POST /internal/v1/turn/perf
|
|
// {"kind":"main","conv":"c…","iter":0,"complete":true,"external":false,
|
|
// "stats":{…StatsEvent…},"prefix":[…empreintes…]}
|
|
// → {"kind":"main","lost":N,"lost_after":"…","lost_alert":true}
|
|
//
|
|
// kind : main (tour), verify (passe de vérification du mode Code) ou compact
|
|
// (résumé de compaction, relevé dans la réponse entière par la façade).
|
|
// prefix : empreintes cumulées des messages envoyés (perfPrefix), calculées
|
|
// par l'appelant — elles n'ont à être cohérentes qu'avec ses propres envois,
|
|
// d'une complétion à la suivante de la même discussion. La sonde du gabarit
|
|
// n'en part pas : la façade la tient (facadeTplCaps).
|
|
|
|
const internalTurnPerfMaxBody = 8 << 20
|
|
|
|
func handleInternalTurnPerf(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
w.Header().Set("Allow", http.MethodPost)
|
|
sendJSON(w, http.StatusMethodNotAllowed, map[string]any{"error": "POST attendu"})
|
|
return
|
|
}
|
|
var in struct {
|
|
Kind string `json:"kind"`
|
|
Conv string `json:"conv"`
|
|
Iter int `json:"iter"`
|
|
Complete bool `json:"complete"`
|
|
External bool `json:"external"`
|
|
Stats StatsEvent `json:"stats"`
|
|
Prefix []uint64 `json:"prefix"`
|
|
}
|
|
raw, err := io.ReadAll(io.LimitReader(r.Body, internalTurnPerfMaxBody+1))
|
|
if err != nil || len(raw) > internalTurnPerfMaxBody || json.Unmarshal(raw, &in) != nil {
|
|
sendJSON(w, http.StatusBadRequest, map[string]any{"error": "télémétrie illisible"})
|
|
return
|
|
}
|
|
if in.Kind == "" {
|
|
in.Kind = perfMain
|
|
}
|
|
var prefix []uint64
|
|
if in.Complete {
|
|
prefix = in.Prefix
|
|
}
|
|
rec := perfRecord(perfRecFromStats(perfTag{kind: in.Kind, conv: in.Conv}, in.Iter, in.Complete, in.Stats), prefix)
|
|
alert := false
|
|
if in.Complete && !in.External && ((rec.Lost != nil && *rec.Lost > 0) || (rec.Cached != nil && *rec.Cached == 0)) {
|
|
alert = perfAlert(rec, perfLostAlertAt(ReadConfig()))
|
|
}
|
|
sendJSON(w, http.StatusOK, map[string]any{
|
|
"kind": rec.Kind, "lost": rec.Lost, "lost_after": rec.LostAfter, "lost_alert": alert,
|
|
})
|
|
}
|