mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 06:58:14 +02:00
Envois simultanes serialises, et pas de controle d'espace disque
Deux defauts trouves en relisant le code de l'envoi en morceaux. Le verrou global etait tenu pendant l'ecriture disque et le renommage. Or le client lance un envoi PAR FICHIER JOINT, de front : trois fichiers s'attendaient donc les uns les autres, chacun bloquant les suivants jusqu'a sa derniere tranche. Le verrou global ne protege plus que la table des sessions ; l'ecriture se fait sous le verrou de la session. Un drapeau `busy` empeche le menage de fermer un fichier sous les pieds de la requete qui l'ecrit. Test : 3 fichiers de 20 Mo en parallele, contenus distincts, aucun melange. Rien ne verifiait la place disque : un envoi d'un gigaoctet pouvait remplir le volume de la machine qui fait tourner le modele, ou vivent aussi llama-server, la base et les journaux. Le client annonce la taille au premier morceau, le serveur refuse en 507 s'il ne reste pas la place plus 512 Mo de marge. La taille annoncee n'engage que le client : le plafond reel reste verifie morceau par morceau. Aussi : Sync() avant publication (un tampon non vide donne un fichier incomplet), et cote client une tranche vide sans marque de fin arrete le telechargement au lieu de boucler indefiniment.
This commit is contained in:
1 parent
78423276e7
commit
6d36464971
5 files changed
+146
-18
No files matched your search
@@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -302,3 +303,55 @@ func TestChatFileB64ForE2E(t *testing.T) {
|
||||
t.Fatalf("fichier reconstitué : %d octets, attendu %d", len(got), len(raw))
|
||||
}
|
||||
}
|
||||
|
||||
// Plusieurs fichiers partent DE FRONT depuis le navigateur (un envoi par pièce
|
||||
// jointe). Les sessions doivent donc être indépendantes : le verrou global ne
|
||||
// protège que la table, l'écriture se fait sous le verrou de la session.
|
||||
func TestChatUploadConcurrentSessions(t *testing.T) {
|
||||
const files, chunks = 4, 6
|
||||
var wg sync.WaitGroup
|
||||
paths := make([]string, files)
|
||||
errs := make([]string, files)
|
||||
for i := 0; i < files; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
id, want := "", ""
|
||||
for c := 0; c < chunks; c++ {
|
||||
piece := strings.Repeat(string(rune('A'+i)), 100+c)
|
||||
want += piece
|
||||
code, resp := uploadChunk(t, map[string]any{
|
||||
"name": fmt.Sprintf("concurrent-%d.txt", i),
|
||||
"data": base64.StdEncoding.EncodeToString([]byte(piece)),
|
||||
"id": id, "more": c < chunks-1,
|
||||
})
|
||||
if code != 200 {
|
||||
errs[i] = fmt.Sprintf("morceau %d : code %d (%v)", c, code, resp["error"])
|
||||
return
|
||||
}
|
||||
if v, ok := resp["id"].(string); ok && v != "" {
|
||||
id = v
|
||||
}
|
||||
if c == chunks-1 {
|
||||
abs, _ := resp["abs"].(string)
|
||||
paths[i] = abs
|
||||
got, err := os.ReadFile(abs)
|
||||
if err != nil || string(got) != want {
|
||||
errs[i] = fmt.Sprintf("contenu melange : %d octets lus, %d attendus (err %v)", len(got), len(want), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
for _, p := range paths {
|
||||
if p != "" {
|
||||
defer os.Remove(p)
|
||||
}
|
||||
}
|
||||
for i, e := range errs {
|
||||
if e != "" {
|
||||
t.Fatalf("fichier %d : %s", i, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user