Amélioration de l'exploitation des PDF par l'IA
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m44s
Build & Push Images / build (core) (push) Successful in 2m0s
Build & Push Images / build-switcher (push) Successful in 23s
Build & Push Images / build (web) (push) Successful in 1m50s

Amélioration des feedbacks en cas d'erreur d'exploitation des PDF
This commit is contained in:
2026-06-12 01:28:45 +02:00
parent 0799c850ec
commit 7f519588b6
7 changed files with 324 additions and 17 deletions

View File

@@ -31,8 +31,13 @@ public class CampaignImportController {
private static final Logger log = LoggerFactory.getLogger(CampaignImportController.class);
/** Timeout SSE généreux : un import de livre entier peut durer plusieurs minutes. */
private static final long IMPORT_SSE_TIMEOUT_MS = 15 * 60 * 1000L;
/**
* Timeout SSE = durée TOTALE maximale de l'import (pas un timeout d'inactivité :
* les heartbeats ne le réarment pas). Un livre entier sur un modèle local peut
* largement dépasser 15 min → 60 min. La déconnexion du client reste détectée
* immédiatement par ailleurs (échec d'envoi → interruption de l'import).
*/
private static final long IMPORT_SSE_TIMEOUT_MS = 60 * 60 * 1000L;
private final CampaignImportService campaignImportService;
private final TaskExecutor taskExecutor;
@@ -66,7 +71,15 @@ public class CampaignImportController {
// amont (ClientGoneException remonte dans le doOnNext du WebClient →
// annule la souscription → le Brain voit la coupure et stoppe le LLM).
AtomicBoolean clientGone = new AtomicBoolean(false);
emitter.onTimeout(() -> clientGone.set(true));
emitter.onTimeout(() -> {
// Timeout = durée totale dépassée, mais la connexion est encore vivante :
// on envoie une vraie erreur au navigateur AVANT de fermer (sinon le flux
// se termine en silence et l'UI reste figée sur la barre de progression).
sendError(emitter, clientGone,
"L'import a dépassé la durée maximale autorisée et a été interrompu. "
+ "Réessayez avec un modèle plus rapide ou un PDF plus petit.");
clientGone.set(true);
});
emitter.onError(e -> clientGone.set(true));
taskExecutor.execute(() -> {

View File

@@ -35,8 +35,13 @@ public class GameSystemController {
private static final Logger log = LoggerFactory.getLogger(GameSystemController.class);
/** Timeout SSE généreux : un import de livre entier peut durer plusieurs minutes. */
private static final long IMPORT_SSE_TIMEOUT_MS = 15 * 60 * 1000L;
/**
* Timeout SSE = durée TOTALE maximale de l'import (pas un timeout d'inactivité :
* les heartbeats ne le réarment pas). Un livre entier sur un modèle local peut
* largement dépasser 15 min → 60 min. La déconnexion du client reste détectée
* immédiatement par ailleurs (échec d'envoi → interruption de l'import).
*/
private static final long IMPORT_SSE_TIMEOUT_MS = 60 * 60 * 1000L;
private final GameSystemService gameSystemService;
private final GameSystemMapper gameSystemMapper;
@@ -148,7 +153,15 @@ public class GameSystemController {
// amont (l'exception ClientGone remonte dans le doOnNext du WebClient →
// annule la souscription → le Brain voit la coupure et stoppe le LLM).
AtomicBoolean clientGone = new AtomicBoolean(false);
emitter.onTimeout(() -> clientGone.set(true));
emitter.onTimeout(() -> {
// Timeout = durée totale dépassée, mais la connexion est encore vivante :
// on envoie une vraie erreur au navigateur AVANT de fermer (sinon le flux
// se termine en silence et l'UI reste figée sur la barre de progression).
sendImportError(emitter, clientGone,
"L'import a dépassé la durée maximale autorisée et a été interrompu. "
+ "Réessayez avec un modèle plus rapide ou un PDF plus petit.");
clientGone.set(true);
});
emitter.onError(e -> clientGone.set(true));
taskExecutor.execute(() -> {