From 9624ff93f0f03e2023b3be8c292612d2dc8be160 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Fri, 2 Jan 2026 22:33:11 +0100 Subject: [PATCH] fix: ws timeout --- .../fr/titionfire/ffsaf/ws/CompetitionWS.java | 27 ++++++++++++-- .../titionfire/ffsaf/ws/ExecutorProducer.java | 19 ++++++++++ .../titionfire/ffsaf/ws/recv/RCardboard.java | 37 +++++++++---------- .../titionfire/ffsaf/ws/recv/RCategorie.java | 8 ++-- .../fr/titionfire/ffsaf/ws/recv/RMatch.java | 18 ++++----- .../titionfire/ffsaf/ws/send/SSCardboard.java | 5 +-- .../titionfire/ffsaf/ws/send/SSCategorie.java | 25 ++++++------- .../fr/titionfire/ffsaf/ws/send/SSMatch.java | 21 +++++------ src/main/resources/application.properties | 1 + 9 files changed, 98 insertions(+), 63 deletions(-) create mode 100644 src/main/java/fr/titionfire/ffsaf/ws/ExecutorProducer.java diff --git a/src/main/java/fr/titionfire/ffsaf/ws/CompetitionWS.java b/src/main/java/fr/titionfire/ffsaf/ws/CompetitionWS.java index 9e3b5d3..edd991b 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/CompetitionWS.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/CompetitionWS.java @@ -16,6 +16,7 @@ import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.PostConstruct; import jakarta.inject.Inject; +import jakarta.inject.Named; import jakarta.ws.rs.ForbiddenException; import org.jboss.logging.Logger; @@ -23,6 +24,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.time.Duration; import java.util.*; +import java.util.concurrent.Executor; import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER; @@ -40,7 +42,7 @@ public class CompetitionWS { RCategorie rCategorie; @Inject - RRegister rRegister; + RRegister rRegister; @Inject RCardboard rCardboard; @@ -51,6 +53,15 @@ public class CompetitionWS { @Inject CompetPermService competPermService; + @SuppressWarnings("CdiInjectionPointsInspection") + @Inject + OpenConnections connections; + + @Inject + @Named("notify-executor") + Executor notifyExecutor; + private static Executor executor; + @Inject CompetitionRepository competitionRepository; @@ -79,6 +90,8 @@ public class CompetitionWS { getWSReceiverMethods(RCategorie.class, rCategorie); getWSReceiverMethods(RRegister.class, rRegister); getWSReceiverMethods(RCardboard.class, rCardboard); + + executor = notifyExecutor; } @OnOpen @@ -186,7 +199,7 @@ public class CompetitionWS { // return Uni.createFrom().item(new Message<>(message.uuid(), message.code(), MessageType.REPLY, "ko")); } - public static Uni sendNotifyToOtherEditor(WebSocketConnection connection, String code, Object data) { + public static void sendNotifyToOtherEditor(WebSocketConnection connection, String code, Object data) { String uuid = connection.pathParam("uuid"); List> queue = new ArrayList<>(); @@ -198,7 +211,15 @@ public class CompetitionWS { } }); - return Uni.join().all(queue).andCollectFailures().onFailure().recoverWithNull().replaceWithVoid(); + Uni.join().all(queue) + .andCollectFailures() + .runSubscriptionOn(executor) + .subscribeAsCompletionStage() + .whenComplete((v, t) -> { + if (t != null) { + LOGGER.error("Error sending ws_out message", t); + } + }); } @OnError diff --git a/src/main/java/fr/titionfire/ffsaf/ws/ExecutorProducer.java b/src/main/java/fr/titionfire/ffsaf/ws/ExecutorProducer.java new file mode 100644 index 0000000..1491353 --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/ws/ExecutorProducer.java @@ -0,0 +1,19 @@ +package fr.titionfire.ffsaf.ws; + +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Named; +import jakarta.inject.Singleton; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +@Singleton +public class ExecutorProducer { + + @Produces + @Named("notify-executor") + public Executor produceNotifyExecutor() { + // Créez un pool de threads avec une taille fixe (par exemple, 10 threads) + return Executors.newFixedThreadPool(10); + } +} diff --git a/src/main/java/fr/titionfire/ffsaf/ws/recv/RCardboard.java b/src/main/java/fr/titionfire/ffsaf/ws/recv/RCardboard.java index 59b6360..202f538 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/recv/RCardboard.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/recv/RCardboard.java @@ -80,35 +80,32 @@ public class RCardboard { return Uni.createFrom().nullItem(); return Panache.withTransaction(() -> cardboardRepository.persist(cardboardModel)); })) - .call(model -> SSCardboard.sendCardboard(connection, CardboardEntity.fromModel(model))) + .invoke(model -> SSCardboard.sendCardboard(connection, CardboardEntity.fromModel(model))) .replaceWithVoid(); } @WSReceiver(code = "getCardboardWithoutThis", permission = PermLevel.VIEW) public Uni getCardboardWithoutThis(WebSocketConnection connection, Long matchId) { return getById(matchId, connection) - .chain(matchModel -> cardboardRepository.list("compet = ?1 AND match != ?2", matchModel.getCategory().getCompet(), matchModel) + .chain(matchModel -> cardboardRepository.list("compet = ?1 AND match != ?2", + matchModel.getCategory().getCompet(), matchModel) .map(models -> { CardboardAllMatch out = new CardboardAllMatch(); - models.stream().filter(c -> (matchModel.getC1_id() != null - && Objects.equals(c.getComb(), matchModel.getC1_id())) - || (matchModel.getC1_guest() != null - && Objects.equals(c.getGuestComb(), matchModel.getC1_guest()))) - .forEach(c -> { - out.c1_yellow += c.getYellow(); - out.c1_red += c.getRed(); - }); - - models.stream().filter(c -> (matchModel.getC2_id() != null - && Objects.equals(c.getComb(), matchModel.getC2_id())) - || (matchModel.getC2_guest() != null - && Objects.equals(c.getGuestComb(), matchModel.getC2_guest()))) - .forEach(c -> { - out.c2_yellow += c.getYellow(); - out.c2_red += c.getRed(); - }); - + for (CardboardModel c : models) { + if ((matchModel.getC1_id() != null && Objects.equals(c.getComb(), + matchModel.getC1_id())) || (matchModel.getC1_guest() != null && Objects.equals( + c.getGuestComb(), matchModel.getC1_guest()))) { + out.c1_yellow += c.getYellow(); + out.c1_red += c.getRed(); + } + if ((matchModel.getC2_id() != null && Objects.equals(c.getComb(), + matchModel.getC2_id())) || (matchModel.getC2_guest() != null && Objects.equals( + c.getGuestComb(), matchModel.getC2_guest()))) { + out.c2_yellow += c.getYellow(); + out.c2_red += c.getRed(); + } + } return out; })); } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java b/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java index 317ff0d..68e01ac 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java @@ -97,7 +97,7 @@ public class RCategorie { return categoryRepository.create(categoryModel); }) - .call(cat -> SSCategorie.sendAddCategory(connection, cat)) + .invoke(cat -> SSCategorie.sendAddCategory(connection, cat)) .map(CategoryModel::getId); } @@ -121,7 +121,7 @@ public class RCategorie { Uni finalUni = uni; return Panache.withTransaction(() -> finalUni); }) - .call(cat -> SSCategorie.sendCategory(connection, cat)) + .invoke(cat -> SSCategorie.sendCategory(connection, cat)) .replaceWithVoid(); } @@ -202,7 +202,7 @@ public class RCategorie { .call(__ -> treeRepository.flush()) .call(cat -> treeRepository.list("category = ?1 AND level != 0", cat.getId()) .map(treeModels -> treeModels.stream().map(TreeEntity::fromModel).toList()) - .chain(trees -> SSCategorie.sendTreeCategory(connection, trees))) + .invoke(trees -> SSCategorie.sendTreeCategory(connection, trees))) .replaceWithVoid(); } @@ -212,7 +212,7 @@ public class RCategorie { .call(cat -> Panache.withTransaction(() -> treeRepository.delete("category = ?1", cat.getId()) .call(__ -> matchRepository.delete("category = ?1", cat)))) .chain(cat -> Panache.withTransaction(() -> categoryRepository.delete(cat))) - .call(__ -> SSCategorie.sendDelCategory(connection, id)) + .invoke(__ -> SSCategorie.sendDelCategory(connection, id)) .replaceWithVoid(); } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java b/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java index a28ac3e..d48707d 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java @@ -84,7 +84,7 @@ public class RMatch { })) .chain(categoryModel -> creatMatch(categoryModel, m)) .chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm))) - .call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm))) + .invoke(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm))) .replaceWithVoid(); } @@ -121,7 +121,7 @@ public class RMatch { mm.setC2_guest(null); })) .chain(mm -> Panache.withTransaction(() -> matchRepository.persist(mm))) - .call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm))) + .invoke(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm))) .replaceWithVoid(); } @@ -136,7 +136,7 @@ public class RMatch { m.getCategory_ord())) .invoke(m -> m.setCategory_ord(order.pos)) .call(m -> Panache.withTransaction(() -> matchRepository.persist(m))) - .call(mm -> SSMatch.sendMatchOrder(connection, order)) + .invoke(mm -> SSMatch.sendMatchOrder(connection, order)) .replaceWithVoid(); } @@ -163,12 +163,12 @@ public class RMatch { .call(mm -> { if (mm.isEnd() && mm.win() != old_win && mm.getCategory_ord() == -42) { return updateEndAndTree(mm, new ArrayList<>()) - .call(l -> SSMatch.sendMatch(connection, l)); + .invoke(l -> SSMatch.sendMatch(connection, l)); } return Uni.createFrom().nullItem(); }); }) - .call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm))) + .invoke(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm))) .replaceWithVoid(); } @@ -189,7 +189,7 @@ public class RMatch { }) .invoke(mm -> toSend.add(MatchEntity.fromModel(mm))) .chain(mm -> updateEndAndTree(mm, toSend)) - .call(__ -> SSMatch.sendMatch(connection, toSend)) + .invoke(__ -> SSMatch.sendMatch(connection, toSend)) .replaceWithVoid(); } @@ -278,7 +278,7 @@ public class RMatch { public Uni deleteMatch(WebSocketConnection connection, Long idMatch) { return getById(idMatch, connection) .chain(matchModel -> Panache.withTransaction(() -> matchRepository.delete(matchModel))) - .call(__ -> SSMatch.sendDeleteMatch(connection, idMatch)) + .invoke(__ -> SSMatch.sendDeleteMatch(connection, idMatch)) .replaceWithVoid(); } @@ -295,7 +295,7 @@ public class RMatch { .call(cm -> data.matchesToRemove.isEmpty() ? Uni.createFrom().voidItem() : (Panache.withTransaction( () -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm)) - .call(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove)))) + .invoke(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove)))) .call(cm -> Panache.withSession(() -> matchRepository.list("id IN ?1 AND category = ?2", Stream.concat(data.matchOrderToUpdate.keySet().stream(), data.matchPouleToUpdate.keySet().stream()) @@ -321,7 +321,7 @@ public class RMatch { .chain(mm -> mm.isEmpty() ? Uni.createFrom().voidItem() : Panache.withTransaction(() -> matchRepository.create(mm)) .invoke(__ -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList()))) - .call(__ -> SSMatch.sendMatch(connection, matches)) + .invoke(__ -> SSMatch.sendMatch(connection, matches)) .replaceWithVoid(); } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/send/SSCardboard.java b/src/main/java/fr/titionfire/ffsaf/ws/send/SSCardboard.java index 31963b1..c7b17d1 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/send/SSCardboard.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/send/SSCardboard.java @@ -3,11 +3,10 @@ package fr.titionfire.ffsaf.ws.send; import fr.titionfire.ffsaf.domain.entity.CardboardEntity; import fr.titionfire.ffsaf.ws.CompetitionWS; import io.quarkus.websockets.next.WebSocketConnection; -import io.smallrye.mutiny.Uni; public class SSCardboard { - public static Uni sendCardboard(WebSocketConnection connection, CardboardEntity cardboardEntity) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendCardboard", cardboardEntity); + public static void sendCardboard(WebSocketConnection connection, CardboardEntity cardboardEntity) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendCardboard", cardboardEntity); } } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/send/SSCategorie.java b/src/main/java/fr/titionfire/ffsaf/ws/send/SSCategorie.java index e981080..76a6a53 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/send/SSCategorie.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/send/SSCategorie.java @@ -5,33 +5,32 @@ import fr.titionfire.ffsaf.domain.entity.TreeEntity; import fr.titionfire.ffsaf.ws.CompetitionWS; import fr.titionfire.ffsaf.ws.recv.RCategorie; import io.quarkus.websockets.next.WebSocketConnection; -import io.smallrye.mutiny.Uni; import java.util.List; public class SSCategorie { - public static Uni sendAddCategory(WebSocketConnection connection, CategoryModel category) { - return SSCategorie.sendAddCategory(connection, RCategorie.JustCategorie.from(category)); + public static void sendAddCategory(WebSocketConnection connection, CategoryModel category) { + SSCategorie.sendAddCategory(connection, RCategorie.JustCategorie.from(category)); } - public static Uni sendAddCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendAddCategory", justCategorie); + public static void sendAddCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendAddCategory", justCategorie); } - public static Uni sendCategory(WebSocketConnection connection, CategoryModel category) { - return SSCategorie.sendCategory(connection, RCategorie.JustCategorie.from(category)); + public static void sendCategory(WebSocketConnection connection, CategoryModel category) { + SSCategorie.sendCategory(connection, RCategorie.JustCategorie.from(category)); } - public static Uni sendCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendCategory", justCategorie); + public static void sendCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendCategory", justCategorie); } - public static Uni sendTreeCategory(WebSocketConnection connection, List treeEntities) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendTreeCategory", treeEntities); + public static void sendTreeCategory(WebSocketConnection connection, List treeEntities) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendTreeCategory", treeEntities); } - public static Uni sendDelCategory(WebSocketConnection connection, Long id) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendDelCategory", id); + public static void sendDelCategory(WebSocketConnection connection, Long id) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendDelCategory", id); } } diff --git a/src/main/java/fr/titionfire/ffsaf/ws/send/SSMatch.java b/src/main/java/fr/titionfire/ffsaf/ws/send/SSMatch.java index b66911d..1b04815 100644 --- a/src/main/java/fr/titionfire/ffsaf/ws/send/SSMatch.java +++ b/src/main/java/fr/titionfire/ffsaf/ws/send/SSMatch.java @@ -4,29 +4,28 @@ import fr.titionfire.ffsaf.domain.entity.MatchEntity; import fr.titionfire.ffsaf.ws.CompetitionWS; import fr.titionfire.ffsaf.ws.recv.RMatch; import io.quarkus.websockets.next.WebSocketConnection; -import io.smallrye.mutiny.Uni; import java.util.List; public class SSMatch { - public static Uni sendMatch(WebSocketConnection connection, MatchEntity matchEntity) { - return SSMatch.sendMatch(connection, List.of(matchEntity)); + public static void sendMatch(WebSocketConnection connection, MatchEntity matchEntity) { + SSMatch.sendMatch(connection, List.of(matchEntity)); } - public static Uni sendMatch(WebSocketConnection connection, List matchEntities) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatch", matchEntities); + public static void sendMatch(WebSocketConnection connection, List matchEntities) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatch", matchEntities); } - public static Uni sendMatchOrder(WebSocketConnection connection, RMatch.MatchOrder matchOrder) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatchOrder", matchOrder); + public static void sendMatchOrder(WebSocketConnection connection, RMatch.MatchOrder matchOrder) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatchOrder", matchOrder); } - public static Uni sendDeleteMatch(WebSocketConnection connection, Long l) { - return SSMatch.sendDeleteMatch(connection, List.of(l)); + public static void sendDeleteMatch(WebSocketConnection connection, Long l) { + SSMatch.sendDeleteMatch(connection, List.of(l)); } - public static Uni sendDeleteMatch(WebSocketConnection connection, List longs) { - return CompetitionWS.sendNotifyToOtherEditor(connection, "sendDeleteMatch", longs); + public static void sendDeleteMatch(WebSocketConnection connection, List longs) { + CompetitionWS.sendNotifyToOtherEditor(connection, "sendDeleteMatch", longs); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3fe3d56..423ffc7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,6 +8,7 @@ quarkus.hibernate-orm.database.generation=update quarkus.hibernate-orm.physical-naming-strategy=fr.titionfire.ffsaf.data.SafcaNamingStrategy quarkus.hibernate-orm.dialect=fr.titionfire.ffsaf.data.CustomPostgreSQLDialect +quarkus.datasource.jdbc.reactive.max-size=40 quarkus.http.cors.enabled=true quarkus.quartz.start-mode=forced -- 2.49.0