diff --git a/brain/app/main.py b/brain/app/main.py index f975479..cb5b57a 100644 --- a/brain/app/main.py +++ b/brain/app/main.py @@ -66,7 +66,7 @@ from app.infrastructure.pdf_extractor import PyMuPdfTextExtractor app = FastAPI( title="LoreMind Brain", description="Backend IA pour la génération de contenu narratif.", - version="0.11.1-beta", + version="0.11.2-beta", ) logger = logging.getLogger(__name__) diff --git a/core/pom.xml b/core/pom.xml index ffb19b7..e9441ec 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -14,7 +14,7 @@ com.loremind loremind-core - 0.11.1-beta + 0.11.2-beta LoreMind Core Backend Core - Architecture Hexagonale diff --git a/core/src/main/java/com/loremind/infrastructure/web/controller/NotebookController.java b/core/src/main/java/com/loremind/infrastructure/web/controller/NotebookController.java index cd258bd..51b8c68 100644 --- a/core/src/main/java/com/loremind/infrastructure/web/controller/NotebookController.java +++ b/core/src/main/java/com/loremind/infrastructure/web/controller/NotebookController.java @@ -28,7 +28,10 @@ import java.util.Map; @RequestMapping("/api/notebooks") public class NotebookController { - private static final long SSE_TIMEOUT_MS = 10 * 60 * 1000L; + // L'analyse approfondie (map-reduce sur tout le doc) peut être longue sur un gros + // livre / un modèle lent → 30 min. Pour aller plus vite : modèle gros-contexte + // (moins de lots). Au-delà, l'expiration est gérée proprement (pas de crash). + private static final long SSE_TIMEOUT_MS = 30 * 60 * 1000L; private final NotebookService service; private final NotebookChatStreamer chatStreamer; @@ -143,13 +146,18 @@ public class NotebookController { return emitter; } - // --- Helpers SSE (mêmes conventions que AiChatController) --- + // --- Helpers SSE --- + // IMPORTANT : on attrape AUSSI IllegalStateException. Si le flux a déjà été fermé + // (timeout async, client déconnecté), `emitter.send/complete` la lève — et comme + // ces helpers tournent dans un thread d'exécuteur, une exception non gérée y + // remontait jusqu'au pool ("Exception in thread task-1: ResponseBodyEmitter has + // already completed"). On l'ignore silencieusement : il n'y a plus rien à envoyer. private void sendToken(SseEmitter emitter, String token) { try { emitter.send(SseEmitter.event().name("token").data("{\"token\":" + jsonEscape(token) + "}")); - } catch (IOException e) { - emitter.completeWithError(e); + } catch (IOException | IllegalStateException e) { + // flux fermé/expiré : on cesse d'écrire } } @@ -157,8 +165,8 @@ public class NotebookController { try { emitter.send(SseEmitter.event().name("progress") .data("{\"current\":" + p.current() + ",\"total\":" + p.total() + "}")); - } catch (IOException e) { - emitter.completeWithError(e); + } catch (IOException | IllegalStateException e) { + // flux fermé/expiré : on cesse d'écrire } } @@ -166,8 +174,8 @@ public class NotebookController { try { emitter.send(SseEmitter.event().name("done").data("{}")); emitter.complete(); - } catch (IOException e) { - emitter.completeWithError(e); + } catch (IOException | IllegalStateException e) { + // flux déjà fermé/expiré : rien à compléter } } @@ -176,8 +184,8 @@ public class NotebookController { String message = error.getMessage() != null ? error.getMessage() : error.getClass().getSimpleName(); emitter.send(SseEmitter.event().name("error").data("{\"message\":" + jsonEscape(message) + "}")); emitter.complete(); - } catch (IOException ioe) { - emitter.completeWithError(ioe); + } catch (IOException | IllegalStateException e) { + // flux déjà fermé/expiré : rien à envoyer } } diff --git a/web/package-lock.json b/web/package-lock.json index 1860e28..c7c36f4 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "loremind-web", - "version": "0.11.1-beta", + "version": "0.11.2-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "loremind-web", - "version": "0.11.1-beta", + "version": "0.11.2-beta", "dependencies": { "@angular/animations": "^17.0.0", "@angular/common": "^17.0.0", diff --git a/web/package.json b/web/package.json index cc02ffc..001b8e5 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "loremind-web", - "version": "0.11.1-beta", + "version": "0.11.2-beta", "description": "LoreMind Frontend - Angular", "scripts": { "ng": "ng",