Chat-Import großer Workspaces scheitert: 30-s-Idle-Timeout, RAM-Pufferung des Upload-Bodys, stiller Workspace-Verlust beim Export #34

Closed
opened 2026-10-12 17:29:55 +00:00 by alf · 1 comment
Owner

Symptom: Import eines .irischat mit großem Workspace (LightCraft, 7,4 GB) scheitert mit „Hochladen der .irischat-Datei zum Server fehlgeschlagen“ (Client-Log: uploadFileToTemp error — Die Netzwerkverbindung wurde unterbrochen, genau 30,3 s nach Start).

Ursachen und Fix (alle in einem Zug):

  1. Idle-Timeout: IrisRemoteServer.acceptConnection setzt einen 30-s-Timer, der erst abgebrochen wird, wenn der GANZE Request gelesen ist. Ein Multi-GB-Upload dauert länger → Server kappt die laufende Übertragung. Fix: Timer wird bei jedem empfangenen Chunk neu gesetzt (echter Leerlauf-Timeout).
  2. Quadratisches Kopieren: readHTTPRequest kopiert den bisherigen Puffer bei jedem 64-KB-Chunk (Data(buffer[…]), Copy-on-Write beim Anhängen). Fix: Header einmal parsen, Body-Bytes zählen, Puffer in einem Akkumulator-Objekt halten, 1-MB-Chunks.
  3. Streaming-Upload: Body von POST /file/upload und /backup/upload wird ab 8 MB (nur für authentifizierte Requests) direkt in eine Temp-Datei geschrieben statt in den RAM; die Handler kopieren den Multipart-Dateiteil blockweise ins Ziel. Der Client (uploadFileToTemp) baut den Multipart-Body als Datei und lädt per upload(for:fromFile:) statt die Datei zweimal in den RAM zu laden.
  4. Stiller Workspace-Verlust beim Export (IrisClient): downloadAndExtractWorkspace gibt bei jedem Fehler nil zurück, der Export läuft ohne Workspace weiter → leerer Workspace nach dem Import. Fix: existiert der Workspace laut GET /file/size, bricht ein Fehler den Export mit klarer Meldung ab. unzip-Exit 1 (nur Warnungen) gilt nicht mehr als Fehler.

Beleg: Log 2026-10-12 19:23:53 Start, 19:24:23 Abbruch.

**Symptom:** Import eines `.irischat` mit großem Workspace (LightCraft, 7,4 GB) scheitert mit „Hochladen der .irischat-Datei zum Server fehlgeschlagen“ (Client-Log: `uploadFileToTemp error — Die Netzwerkverbindung wurde unterbrochen`, genau 30,3 s nach Start). **Ursachen und Fix (alle in einem Zug):** 1. **Idle-Timeout:** `IrisRemoteServer.acceptConnection` setzt einen 30-s-Timer, der erst abgebrochen wird, wenn der GANZE Request gelesen ist. Ein Multi-GB-Upload dauert länger → Server kappt die laufende Übertragung. Fix: Timer wird bei jedem empfangenen Chunk neu gesetzt (echter Leerlauf-Timeout). 2. **Quadratisches Kopieren:** `readHTTPRequest` kopiert den bisherigen Puffer bei jedem 64-KB-Chunk (`Data(buffer[…])`, Copy-on-Write beim Anhängen). Fix: Header einmal parsen, Body-Bytes zählen, Puffer in einem Akkumulator-Objekt halten, 1-MB-Chunks. 3. **Streaming-Upload:** Body von `POST /file/upload` und `/backup/upload` wird ab 8 MB (nur für authentifizierte Requests) direkt in eine Temp-Datei geschrieben statt in den RAM; die Handler kopieren den Multipart-Dateiteil blockweise ins Ziel. Der Client (`uploadFileToTemp`) baut den Multipart-Body als Datei und lädt per `upload(for:fromFile:)` statt die Datei zweimal in den RAM zu laden. 4. **Stiller Workspace-Verlust beim Export (IrisClient):** `downloadAndExtractWorkspace` gibt bei jedem Fehler `nil` zurück, der Export läuft ohne Workspace weiter → leerer Workspace nach dem Import. Fix: existiert der Workspace laut `GET /file/size`, bricht ein Fehler den Export mit klarer Meldung ab. `unzip`-Exit 1 (nur Warnungen) gilt nicht mehr als Fehler. Beleg: Log 2026-10-12 19:23:53 Start, 19:24:23 Abbruch.
alf closed this issue 2026-10-12 17:35:27 +00:00
Author
Owner

Umgesetzt und gemergt (PR #35, main):

  • Idle-Timeout des Servers startet bei jedem empfangenen Chunk neu (vorher: 30 s ab Verbindungsaufbau, der Upload brach nach 30,3 s ab).
  • readHTTPRequest parst Header einmal und hängt Chunks in einem Akkumulator an (vorher quadratisches Kopieren).
  • /file/upload und /backup/upload streamen Bodys ab 8 MB (nur authentifiziert) in eine Temp-Datei; die Handler kopieren den Multipart-Dateiteil blockweise im Hintergrund. Der Client sendet per upload(fromFile:) statt die Datei zweimal in den RAM zu laden.
  • Export (IrisClient): Ein bestätigt vorhandener Workspace, der nicht übertragen werden kann, bricht den Export mit klarer Meldung ab. unzip-Exit 1 (Warnungen) gilt nicht mehr als Fehler.

Geprüft: Builds Iris und IrisClient; Test der Dateiteil-Extraktion mit 64 MB, byte-identisch.

Offen: Live-Test mit dem LightCraft-Chat (7,4 GB) auf beiden Macs mit neuem Build. Das Issue bleibt bis dahin offen. Bekannt und nicht geändert: Staging per copyItem blockiert beim Export die Oberfläche (ca. 4 Min).

**Umgesetzt und gemergt (PR #35, `main`):** - Idle-Timeout des Servers startet bei jedem empfangenen Chunk neu (vorher: 30 s ab Verbindungsaufbau, der Upload brach nach 30,3 s ab). - `readHTTPRequest` parst Header einmal und hängt Chunks in einem Akkumulator an (vorher quadratisches Kopieren). - `/file/upload` und `/backup/upload` streamen Bodys ab 8 MB (nur authentifiziert) in eine Temp-Datei; die Handler kopieren den Multipart-Dateiteil blockweise im Hintergrund. Der Client sendet per `upload(fromFile:)` statt die Datei zweimal in den RAM zu laden. - Export (IrisClient): Ein bestätigt vorhandener Workspace, der nicht übertragen werden kann, bricht den Export mit klarer Meldung ab. `unzip`-Exit 1 (Warnungen) gilt nicht mehr als Fehler. **Geprüft:** Builds `Iris` und `IrisClient`; Test der Dateiteil-Extraktion mit 64 MB, byte-identisch. **Offen:** Live-Test mit dem LightCraft-Chat (7,4 GB) auf beiden Macs mit neuem Build. Das Issue bleibt bis dahin offen. Bekannt und nicht geändert: Staging per `copyItem` blockiert beim Export die Oberfläche (ca. 4 Min).
alf reopened this issue 2026-10-12 17:35:37 +00:00
alf closed this issue 2026-10-16 14:37:39 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/Iris#34
No description provided.