This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch 2.7.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit a12ff645711ccc9871fbb9dc5b72ee77f61e43d6
Author: James Netherton <[email protected]>
AuthorDate: Fri Feb 11 14:09:57 2022 +0000

    Poll for optaplanner results to avoid timeouts on slow machines
---
 integration-tests/optaplanner/pom.xml              | 12 ++-
 .../optaplanner/it/OptaplannerResource.java        | 85 +++++++++++++------
 .../quarkus/component/optaplanner/it/Routes.java   | 15 ++--
 .../component/optaplanner/it/OptaplannerTest.java  | 98 ++++++++++++++++++----
 4 files changed, 159 insertions(+), 51 deletions(-)

diff --git a/integration-tests/optaplanner/pom.xml 
b/integration-tests/optaplanner/pom.xml
index b9c880f..bcf5997 100644
--- a/integration-tests/optaplanner/pom.xml
+++ b/integration-tests/optaplanner/pom.xml
@@ -36,10 +36,6 @@
             <artifactId>camel-quarkus-optaplanner</artifactId>
         </dependency>
         <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-resteasy-jackson</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-direct</artifactId>
         </dependency>
@@ -47,6 +43,14 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-mock</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jsonb</artifactId>
+        </dependency>
 
         <!-- test dependencies -->
         <dependency>
diff --git 
a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java
 
b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java
index e1f9640..3fe3c8a 100644
--- 
a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java
+++ 
b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerResource.java
@@ -16,23 +16,30 @@
  */
 package org.apache.camel.quarkus.component.optaplanner.it;
 
-import java.util.concurrent.CompletableFuture;
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.component.optaplanner.OptaPlannerConstants;
 import 
org.apache.camel.quarkus.component.optaplanner.it.bootstrap.DataGenerator;
+import org.apache.camel.quarkus.component.optaplanner.it.domain.Room;
 import org.apache.camel.quarkus.component.optaplanner.it.domain.TimeTable;
-import org.jboss.logging.Logger;
+import org.apache.camel.quarkus.component.optaplanner.it.domain.Timeslot;
 import org.optaplanner.core.api.solver.SolverManager;
 import org.optaplanner.core.api.solver.SolverStatus;
 
@@ -41,8 +48,6 @@ import org.optaplanner.core.api.solver.SolverStatus;
 @Produces(MediaType.APPLICATION_JSON)
 public class OptaplannerResource {
 
-    private static final Logger LOG = 
Logger.getLogger(OptaplannerResource.class);
-
     public static final Long SINGLETON_TIME_TABLE_ID = 1L;
 
     @Inject
@@ -54,38 +59,68 @@ public class OptaplannerResource {
     @Inject
     CamelContext context;
 
-    @GET
+    @POST
     @Path("solveSync")
-    public TimeTable solveSync() {
+    public void solveSync() {
         if (SolverStatus.NOT_SOLVING == 
solverManager.getSolverStatus(SINGLETON_TIME_TABLE_ID)) {
-            TimeTable finalSolution = producerTemplate.requestBodyAndHeader(
-                    "direct:solveSync", DataGenerator.timeTable,
-                    OptaPlannerConstants.SOLVER_MANAGER, solverManager, 
TimeTable.class);
-            return finalSolution;
+            producerTemplate.sendBodyAndHeader("direct:solveSync", 
DataGenerator.timeTable, OptaPlannerConstants.SOLVER_MANAGER,
+                    solverManager);
         }
-        return DataGenerator.timeTable;
     }
 
-    @GET
+    @POST
     @Path("solveAsync")
-    public TimeTable solveAsync() throws ExecutionException, 
InterruptedException {
+    public void solveAsync() throws ExecutionException, InterruptedException {
         if (SolverStatus.NOT_SOLVING == 
solverManager.getSolverStatus(SINGLETON_TIME_TABLE_ID)) {
-            CompletableFuture<TimeTable> response = 
producerTemplate.asyncRequestBodyAndHeader(
-                    "direct:solveAsync", DataGenerator.timeTable, 
OptaPlannerConstants.SOLVER_MANAGER,
-                    solverManager, TimeTable.class);
+            producerTemplate.sendBodyAndHeader("direct:solveAsync", 
DataGenerator.timeTable,
+                    OptaPlannerConstants.SOLVER_MANAGER, solverManager);
+        }
+    }
 
-            TimeTable finalSolution = response.get();
-            return finalSolution;
+    @POST
+    @Path("consumer/{enable}")
+    public void mangeOptaplannerConsumer(@PathParam("enable") boolean enable) 
throws Exception {
+        if (enable) {
+            context.getRouteController().startRoute("optaplanner-consumer");
+        } else {
+            context.getRouteController().stopRoute("optaplanner-consumer");
         }
-        return DataGenerator.timeTable;
     }
 
     @GET
-    @Path("newBestSolution")
-    public TimeTable getNewBestSolution() {
-        MockEndpoint mockEndpoint = context.getEndpoint("mock:best-solution", 
MockEndpoint.class);
-        return mockEndpoint.getReceivedExchanges().stream().map(
-                exchange -> 
exchange.getMessage().getHeader(OptaPlannerConstants.BEST_SOLUTION, 
TimeTable.class))
-                .findFirst().orElse(null);
+    @Path("solution/{mockEndpointUri}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonObject getSolution(@PathParam("mockEndpointUri") String 
mockEndpointUri) {
+        MockEndpoint mockEndpoint = context.getEndpoint("mock:" + 
mockEndpointUri, MockEndpoint.class);
+        Optional<JsonObject> result = mockEndpoint.getReceivedExchanges()
+                .stream()
+                .map(Exchange::getMessage)
+                .map(message -> {
+                    if (mockEndpointUri.equals("bestSolution")) {
+                        return 
message.getHeader(OptaPlannerConstants.BEST_SOLUTION, TimeTable.class);
+                    } else {
+                        return message.getBody(TimeTable.class);
+                    }
+                })
+                .map(this::extractResults)
+                .findFirst();
+
+        if (result.isPresent()) {
+            mockEndpoint.reset();
+            return result.get();
+        }
+        return extractResults(null);
+    }
+
+    private JsonObject extractResults(TimeTable timeTable) {
+        JsonObjectBuilder builder = Json.createObjectBuilder();
+        if (timeTable != null) {
+            Timeslot timeslot = timeTable.getTimeslotList().get(0);
+            Room room = timeTable.getRoomList().get(0);
+            builder.add("timeslot", timeslot.getId()).add("room", 
room.getId());
+        } else {
+            builder.add("timeslot", "-1").add("room", "-1");
+        }
+        return builder.build();
     }
 }
diff --git 
a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java
 
b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java
index 809cd59..ee83982 100644
--- 
a/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java
+++ 
b/integration-tests/optaplanner/src/main/java/org/apache/camel/quarkus/component/optaplanner/it/Routes.java
@@ -26,15 +26,20 @@ public class Routes extends RouteBuilder {
     public void configure() throws Exception {
 
         // async producer
-        
from("direct:solveAsync").to("optaplanner:anything?useSolverManager=true&async=true&problemId="
-                + OptaplannerResource.SINGLETON_TIME_TABLE_ID);
+        from("direct:solveAsync")
+                
.toF("optaplanner:anything?useSolverManager=true&async=true&problemId=%d",
+                        OptaplannerResource.SINGLETON_TIME_TABLE_ID)
+                .to("mock:solveAsync");
 
         // async consumer
-        from("optaplanner:anything?useSolverManager=true&problemId=" + 
OptaplannerResource.SINGLETON_TIME_TABLE_ID)
-                .to("mock:best-solution");
+        fromF("optaplanner:anything?useSolverManager=true&problemId=%d", 
OptaplannerResource.SINGLETON_TIME_TABLE_ID)
+                .id("optaplanner-consumer")
+                .autoStartup(false)
+                .to("mock:bestSolution");
 
         // sync producer
         from("direct:solveSync")
-                .to("optaplanner:anything?useSolverManager=true&problemId=" + 
OptaplannerResource.SINGLETON_TIME_TABLE_ID);
+                
.toF("optaplanner:anything?useSolverManager=true&problemId=%d", 
OptaplannerResource.SINGLETON_TIME_TABLE_ID)
+                .to("mock:solveSync");
     }
 }
diff --git 
a/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java
 
b/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java
index a519555..70ca5d0 100644
--- 
a/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java
+++ 
b/integration-tests/optaplanner/src/test/java/org/apache/camel/quarkus/component/optaplanner/it/OptaplannerTest.java
@@ -20,40 +20,104 @@ import java.util.concurrent.TimeUnit;
 
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
-import org.apache.camel.quarkus.component.optaplanner.it.domain.TimeTable;
+import io.restassured.path.json.JsonPath;
 import org.junit.jupiter.api.Test;
 
 import static org.awaitility.Awaitility.await;
-import static org.hamcrest.Matchers.notNullValue;
 
 @QuarkusTest
 class OptaplannerTest {
 
     @Test
     public void solveSync() {
+        // Initiate synchronous solving
         RestAssured.given()
-                .get("/optaplanner/solveSync")
+                .post("/optaplanner/solveSync")
                 .then()
-                .statusCode(200)
-                .body("lessonList[0].timeslot", notNullValue(null))
-                .body("lessonList[0].room", notNullValue(null));
+                .statusCode(204);
+
+        // Poll for results
+        await().pollDelay(250, TimeUnit.MILLISECONDS).atMost(1, 
TimeUnit.MINUTES).until(() -> {
+            JsonPath json = RestAssured.given()
+                    .get("/optaplanner/solution/solveSync")
+                    .then()
+                    .statusCode(200)
+                    .extract()
+                    .body()
+                    .jsonPath();
+
+            return json.getLong("timeslot") > -1 && json.getLong("room") > -1;
+        });
     }
 
     @Test
-    public void solveASyncWithConsumer() {
-        // solve async
+    public void solveAsync() {
+        // Initiate asynchronous solving
         RestAssured.given()
-                .get("/optaplanner/solveAsync")
+                .post("/optaplanner/solveAsync")
                 .then()
-                .statusCode(200)
-                .body("lessonList[0].timeslot", notNullValue(null))
-                .body("lessonList[0].room", notNullValue(null));
-
-        await().atMost(10L, TimeUnit.SECONDS).until(() -> {
-            TimeTable result = 
RestAssured.get("/optaplanner/newBestSolution").then().extract().body().as(TimeTable.class);
-            return result != null && 
result.getLessonList().get(0).getTimeslot() != null
-                    && result.getLessonList().get(0).getRoom() != null;
+                .statusCode(204);
+
+        // Poll for results
+        await().pollDelay(250, TimeUnit.MILLISECONDS).atMost(1, 
TimeUnit.MINUTES).until(() -> {
+            JsonPath json = RestAssured.given()
+                    .get("/optaplanner/solution/solveAsync")
+                    .then()
+                    .statusCode(200)
+                    .extract()
+                    .body()
+                    .jsonPath();
+
+            return json.getLong("timeslot") > -1 && json.getLong("room") > -1;
         });
     }
 
+    @Test
+    public void optaplannerConsumerBestSolution() {
+        try {
+            // Start optaplanner consumer
+            RestAssured.given()
+                    .post("/optaplanner/consumer/true")
+                    .then()
+                    .statusCode(204);
+
+            // Initiate asynchronous solving
+            RestAssured.given()
+                    .post("/optaplanner/solveAsync")
+                    .then()
+                    .statusCode(204);
+
+            // Poll for results
+            await().pollDelay(250, TimeUnit.MILLISECONDS).atMost(1, 
TimeUnit.MINUTES).until(() -> {
+                JsonPath json = RestAssured.given()
+                        .get("/optaplanner/solution/solveAsync")
+                        .then()
+                        .statusCode(200)
+                        .extract()
+                        .body()
+                        .jsonPath();
+
+                return json.getLong("timeslot") > -1 && json.getLong("room") > 
-1;
+            });
+
+            await().pollDelay(250, TimeUnit.MILLISECONDS).atMost(1, 
TimeUnit.MINUTES).until(() -> {
+                JsonPath json = RestAssured.given()
+                        .get("/optaplanner/solution/bestSolution")
+                        .then()
+                        .statusCode(200)
+                        .extract()
+                        .body()
+                        .jsonPath();
+
+                return json.getLong("timeslot") > -1 && json.getLong("room") > 
-1;
+            });
+        } finally {
+            // Stop optaplanner consumer
+            RestAssured.given()
+                    .post("/optaplanner/consumer/false")
+                    .then()
+                    .statusCode(204);
+        }
+    }
+
 }

Reply via email to