mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 15:08:16 +02:00
Longues discussions : ne rejouer que la fin, charger le début d'un clic
Inspiré du fenêtrage du fil d'OpenFox (2.0.151+). À chaque ouverture d'onglet, le serveur rejouait TOUT le journal d'affichage : sur une discussion de plusieurs centaines de tours, des dizaines de milliers d'événements traversaient le flux, puis autant de bulles s'installaient dans le DOM que le navigateur devait traîner à chaque rendu. Le replay initial est désormais borné à ses 4000 derniers événements. Rien n'est tronqué sur le disque : le serveur annonce combien d'événements sont restés en arrière, l'interface l'affiche en tête du fil et le bouton « charger le début » se réabonne en demandant le journal entier. Jamais borné sur une reprise de flux (from > 0) : là, le client a déjà le début à l'écran et attend la suite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K6CAgoLJzufeA8rZTSpSpY
This commit is contained in:
8 files changed
+182
-11
No files matched your search
@@ -952,7 +952,18 @@ func coalesceReplay(events []LogEvent, from int) []map[string]any {
|
||||
// de Log[from:] (léger), puis un caught_up, puis le DIRECT événement par événement.
|
||||
// Bloque jusqu'à ce que ctx (la connexion HTTP) soit annulé — la génération, elle,
|
||||
// continue indépendamment. emit renvoie false si l'écriture échoue (client parti).
|
||||
func (c *Conversation) Subscribe(ctx context.Context, from int, emit func(map[string]any) bool) {
|
||||
// replayTailMax borne le nombre d'événements REJOUÉS au chargement d'une
|
||||
// discussion. Ce n'est pas une troncature du journal (rien n'est effacé) : le
|
||||
// début reste sur disque et le client le demande d'un clic (full=true).
|
||||
//
|
||||
// Une discussion de plusieurs centaines de tours rejouait des dizaines de
|
||||
// milliers d'événements à chaque ouverture d'onglet : quelques secondes de voile
|
||||
// de chargement, et autant de bulles dans le DOM que le navigateur devait ensuite
|
||||
// traîner à chaque rendu. On rejoue la fin — ce qu'on vient lire — et on annonce
|
||||
// combien d'événements sont restés en arrière.
|
||||
const replayTailMax = 4000
|
||||
|
||||
func (c *Conversation) Subscribe(ctx context.Context, from int, full bool, emit func(map[string]any) bool) {
|
||||
// Réveille les attentes de cond quand la connexion se ferme.
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
@@ -988,7 +999,19 @@ func (c *Conversation) Subscribe(ctx context.Context, from int, emit func(map[st
|
||||
from = 0
|
||||
}
|
||||
last := from
|
||||
for _, ev := range coalesceReplay(snapshot, from) {
|
||||
events := coalesceReplay(snapshot, from)
|
||||
// Replay borné : on ne garde que la fin, et on DIT au client combien
|
||||
// d'événements manquent devant (il affiche « charger le début »). Jamais
|
||||
// borné sur une reprise de flux (from > 0) : là, le client a déjà tout le
|
||||
// début à l'écran et attend la SUITE.
|
||||
if !full && from == 0 && len(events) > replayTailMax {
|
||||
hidden := len(events) - replayTailMax
|
||||
events = events[hidden:]
|
||||
if !emit(map[string]any{"replay_truncated": hidden}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, ev := range events {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user