Search in sources :

Example 1 with SolverRequest

use of org.acme.schooltimetabling.message.SolverRequest in project optaplanner-quickstarts by kiegroup.

the class TimeTableMessagingHandlerTest method solve.

@Test
@Timeout(TEST_TIMEOUT_SECONDS)
void solve() {
    long problemId = 1L;
    TimeTable unsolvedTimeTable = createTestTimeTable();
    sendSolverRequest(new SolverRequest(problemId, unsolvedTimeTable));
    SolverResponse solverResponse = receiveSolverResponse(MESSAGE_RECEIVE_TIMEOUT_SECONDS);
    assertThat(SolverResponse.ResponseStatus.SUCCESS == solverResponse.getResponseStatus());
    assertThat(problemId == solverResponse.getProblemId());
    assertThat(solverResponse.getTimeTable().getLessonList()).hasSameSizeAs(unsolvedTimeTable.getLessonList());
    assertThat(solverResponse.getTimeTable().getScore().isFeasible()).isTrue();
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) SolverResponse(org.acme.schooltimetabling.message.SolverResponse) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test) Timeout(org.junit.jupiter.api.Timeout)

Example 2 with SolverRequest

use of org.acme.schooltimetabling.message.SolverRequest in project optaplanner-quickstarts by kiegroup.

the class TimeTableResource method solve.

@POST
@Path("solve")
public void solve() throws JsonProcessingException {
    TimeTable timeTable = timeTableRepository.get();
    timeTable.setSolverStatus(SolverStatus.SOLVING_SCHEDULED);
    SolverRequest solverRequest = new SolverRequest(SINGLETON_TIME_TABLE_ID, timeTable);
    String solverRequestJson = objectMapper.writeValueAsString(solverRequest);
    solverRequestEmitter.send(solverRequestJson);
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 3 with SolverRequest

use of org.acme.schooltimetabling.message.SolverRequest in project optaplanner-quickstarts by kiegroup.

the class TimeTableResourceTest method solveAndRetrieve.

@Test
@Timeout(60L)
void solveAndRetrieve() throws JsonProcessingException {
    timeTableResource.solve();
    await().timeout(AWAIT_TIMEOUT).until(solverRequestSink::received, messages -> messages.size() == 1);
    Message<String> solverRequestMessage = solverRequestSink.received().get(0);
    SolverRequest solverRequest = objectMapper.readValue(solverRequestMessage.getPayload(), SolverRequest.class);
    // Assign one lesson to simulate solving.
    TimeTable requestTimeTable = solverRequest.getTimeTable();
    Lesson firstLesson = requestTimeTable.getLessonList().get(0);
    firstLesson.setRoom(requestTimeTable.getRoomList().get(0));
    firstLesson.setTimeslot(requestTimeTable.getTimeslotList().get(0));
    SolverResponse solverResponse = new SolverResponse(solverRequest.getProblemId(), requestTimeTable);
    solverResponseSource.send(objectMapper.writeValueAsString(solverResponse));
    // Wait until the client receives the message and saves the new timetable to a database.
    await().timeout(AWAIT_TIMEOUT).until(timeTableResource::getTimeTable, timeTable -> timeTable.getLessonList().get(0).getRoom() != null);
    Lesson solvedFirstLesson = timeTableResource.getTimeTable().getLessonList().get(0);
    assertThat(solvedFirstLesson.getRoom()).isNotNull();
    assertThat(solvedFirstLesson.getTimeslot()).isNotNull();
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) SolverResponse(org.acme.schooltimetabling.message.SolverResponse) Lesson(org.acme.schooltimetabling.domain.Lesson) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test) Timeout(org.junit.jupiter.api.Timeout)

Example 4 with SolverRequest

use of org.acme.schooltimetabling.message.SolverRequest in project optaplanner-quickstarts by kiegroup.

the class TimeTableMessagingHandler method solve.

@Incoming(SOLVER_REQUEST_CHANNEL)
public CompletionStage<Void> solve(Message<String> solverRequestMessage) {
    return CompletableFuture.runAsync(() -> {
        SolverRequest solverRequest;
        try {
            solverRequest = objectMapper.readValue(solverRequestMessage.getPayload(), SolverRequest.class);
        } catch (Throwable throwable) {
            LOGGER.warn("Unable to deserialize solver request from JSON.", throwable);
            /* Usually a bad request, which should be immediately rejected. No error response can be sent back
                   as the problemId is unknown. Such a NACKed message is redirected to the DLQ (Dead letter queue).
                   Catching the Throwable to make sure no unchecked exceptions are missed. */
            solverRequestMessage.nack(throwable);
            return;
        }
        TimeTable solution;
        try {
            solution = solver.solve(solverRequest.getTimeTable());
            replySuccess(solverRequestMessage, solverRequest.getProblemId(), solution);
        } catch (Throwable throwable) {
            LOGGER.warn("Error during processing a solver request ({}).", solverRequest.getProblemId(), throwable);
            replyFailure(solverRequestMessage, solverRequest.getProblemId(), throwable);
        }
    });
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) Incoming(org.eclipse.microprofile.reactive.messaging.Incoming)

Example 5 with SolverRequest

use of org.acme.schooltimetabling.message.SolverRequest in project optaplanner-quickstarts by kiegroup.

the class TimeTableMessagingHandlerTest method solvingThrowsException.

@Test
@Timeout(TEST_TIMEOUT_SECONDS)
void solvingThrowsException() {
    long problemId = 10L;
    // OptaPlanner doesn't tolerate a null planningId.
    TimeTable timeTableWithIncorrectLesson = new TimeTable(Arrays.asList(new Timeslot(1L, DayOfWeek.MONDAY, LocalTime.NOON, LocalTime.NOON.plusMinutes(30))), Arrays.asList(new Room(1L, "room-A")), Arrays.asList(new Lesson(null, "Math", "A. Touring", "10th grade")));
    sendSolverRequest(new SolverRequest(problemId, timeTableWithIncorrectLesson));
    SolverResponse solverResponse = receiveSolverResponse(MESSAGE_RECEIVE_TIMEOUT_SECONDS);
    assertThat(SolverResponse.ResponseStatus.FAILURE == solverResponse.getResponseStatus());
    assertThat(problemId == solverResponse.getProblemId());
    assertThat(solverResponse.getErrorInfo().getExceptionClassName()).isEqualTo(IllegalArgumentException.class.getName());
    assertThat(solverResponse.getErrorInfo().getExceptionMessage()).startsWith("The planningId (null)");
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) SolverResponse(org.acme.schooltimetabling.message.SolverResponse) Timeslot(org.acme.schooltimetabling.domain.Timeslot) Room(org.acme.schooltimetabling.domain.Room) Lesson(org.acme.schooltimetabling.domain.Lesson) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test) Timeout(org.junit.jupiter.api.Timeout)

Aggregations

TimeTable (org.acme.schooltimetabling.domain.TimeTable)5 SolverRequest (org.acme.schooltimetabling.message.SolverRequest)5 QuarkusTest (io.quarkus.test.junit.QuarkusTest)3 SolverResponse (org.acme.schooltimetabling.message.SolverResponse)3 Test (org.junit.jupiter.api.Test)3 Timeout (org.junit.jupiter.api.Timeout)3 Lesson (org.acme.schooltimetabling.domain.Lesson)2 POST (javax.ws.rs.POST)1 Path (javax.ws.rs.Path)1 Room (org.acme.schooltimetabling.domain.Room)1 Timeslot (org.acme.schooltimetabling.domain.Timeslot)1 Incoming (org.eclipse.microprofile.reactive.messaging.Incoming)1