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:
nathaninline committed 2026-08-10 20:47:00 +02:00
1 parent 78423276e7
commit 6d36464971
5 files changed
+146 -18

No files matched your search

+9 -3
View File
@@ -93,8 +93,12 @@ async function fetchFileB64(path, size, chip){
const r=await jfetch('/api/chat/file?b64=1&len='+DL_CHUNK+'&offset='+off+'&path='+encodeURIComponent(path));
const j=await r.json();
if(!r.ok || !j.ok) throw new Error(j.error||('HTTP '+r.status));
parts.push(b64ToBytes(j.data||''));
off=(j.offset||0)+(parts[parts.length-1].length);
const bytes=b64ToBytes(j.data||'');
parts.push(bytes);
// Une tranche vide sans marque de fin ne ferait pas avancer la boucle : on
// s'arrête plutôt que de tourner indéfiniment sur le même octet.
if(!bytes.length && !j.eof) throw new Error('transfert interrompu');
off=(j.offset||0)+bytes.length;
if(chip && size) chip.title='téléchargement '+Math.round(off*100/size)+' %';
if(j.eof) break;
} while(off<size);
@@ -243,7 +247,9 @@ async function uploadAttach(a){
const end=Math.min(off+ATTACH_CHUNK, a.size);
const data=await readAsBase64(a.file.slice(off, end));
const last=end>=a.size;
const j=await sendChunk({name:a.name, data:data, id:id, more:!last});
// `size` au premier morceau : le serveur vérifie la place disque AVANT
// d'entamer un envoi d'un gigaoctet, plutôt que de le découvrir à la fin.
const j=await sendChunk({name:a.name, data:data, id:id, more:!last, size:(id?0:a.size)});
if(j.id) id=j.id;
off=end;
a.sent=off; renderAttach();