From 0ecb865c2f6ff25d46f58d50d3b77cdfd253632f Mon Sep 17 00:00:00 2001 From: Joris Mancini Date: Thu, 5 Dec 2024 12:18:57 +0100 Subject: [PATCH] feat: avoid computation failure if an error occurs in post run treatment Signed-off-by: Joris Mancini --- .../service/AbstractWorkerService.java | 14 +++++++-- .../computation/service/PostRunException.java | 17 ++++++++++ .../computation/service/ReportService.java | 7 +++-- .../commons/computation/ComputationTest.java | 31 ++++++++++--------- 4 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/powsybl/ws/commons/computation/service/PostRunException.java diff --git a/src/main/java/com/powsybl/ws/commons/computation/service/AbstractWorkerService.java b/src/main/java/com/powsybl/ws/commons/computation/service/AbstractWorkerService.java index 4787ad4..46916bf 100644 --- a/src/main/java/com/powsybl/ws/commons/computation/service/AbstractWorkerService.java +++ b/src/main/java/com/powsybl/ws/commons/computation/service/AbstractWorkerService.java @@ -224,7 +224,13 @@ protected R run(C runContext, UUID resultUuid, AtomicReference rootR preRun(runContext); CompletableFuture future = runAsync(runContext, provider, resultUuid); R result = future == null ? null : observer.observeRun("run", runContext, future::get); - postRun(runContext, rootReporter, result); + try { + postRun(runContext, rootReporter, result); + } catch (Exception e) { + // As the exception occurs after a successful run of the computation we don't want the whole computation to fail + // Then we just log the error + LOGGER.error("An error occurred after computation run", e); + } return result; } @@ -236,7 +242,11 @@ protected R run(C runContext, UUID resultUuid, AtomicReference rootR */ protected void postRun(C runContext, AtomicReference rootReportNode, R ignoredResult) { if (runContext.getReportInfos().reportUuid() != null) { - observer.observe("report.send", runContext, () -> reportService.sendReport(runContext.getReportInfos().reportUuid(), rootReportNode.get())); + try { + observer.observe("report.send", runContext, () -> reportService.sendReport(runContext.getReportInfos().reportUuid(), rootReportNode.get())); + } catch (Exception e) { + throw new PostRunException("An error occurred while sending reports", e); + } } } diff --git a/src/main/java/com/powsybl/ws/commons/computation/service/PostRunException.java b/src/main/java/com/powsybl/ws/commons/computation/service/PostRunException.java new file mode 100644 index 0000000..d05051b --- /dev/null +++ b/src/main/java/com/powsybl/ws/commons/computation/service/PostRunException.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2024, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.ws.commons.computation.service; + +public class PostRunException extends RuntimeException { + public PostRunException(String message) { + super(message); + } + + public PostRunException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/powsybl/ws/commons/computation/service/ReportService.java b/src/main/java/com/powsybl/ws/commons/computation/service/ReportService.java index 6d71675..ead0167 100644 --- a/src/main/java/com/powsybl/ws/commons/computation/service/ReportService.java +++ b/src/main/java/com/powsybl/ws/commons/computation/service/ReportService.java @@ -60,12 +60,13 @@ public void sendReport(UUID reportUuid, ReportNode reportNode) { var headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); + String str; try { - String str = objectMapper.writeValueAsString(reportNode); - restTemplate.exchange(getReportServerURI() + path, HttpMethod.PUT, new HttpEntity<>(str, headers), ReportNode.class); + str = objectMapper.writeValueAsString(reportNode); } catch (JsonProcessingException error) { - throw new PowsyblException("Error sending report", error); + throw new PowsyblException("Impossible to serialize ReportNode", error); } + restTemplate.exchange(getReportServerURI() + path, HttpMethod.PUT, new HttpEntity<>(str, headers), ReportNode.class); } public void deleteReport(UUID reportUuid) { diff --git a/src/test/java/com/powsybl/ws/commons/computation/ComputationTest.java b/src/test/java/com/powsybl/ws/commons/computation/ComputationTest.java index 8dfd238..39c0107 100644 --- a/src/test/java/com/powsybl/ws/commons/computation/ComputationTest.java +++ b/src/test/java/com/powsybl/ws/commons/computation/ComputationTest.java @@ -6,17 +6,7 @@ import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.ws.commons.computation.dto.ReportInfos; -import com.powsybl.ws.commons.computation.service.AbstractComputationObserver; -import com.powsybl.ws.commons.computation.service.AbstractComputationResultService; -import com.powsybl.ws.commons.computation.service.AbstractComputationRunContext; -import com.powsybl.ws.commons.computation.service.AbstractComputationService; -import com.powsybl.ws.commons.computation.service.AbstractResultContext; -import com.powsybl.ws.commons.computation.service.AbstractWorkerService; -import com.powsybl.ws.commons.computation.service.CancelContext; -import com.powsybl.ws.commons.computation.service.ExecutionService; -import com.powsybl.ws.commons.computation.service.NotificationService; -import com.powsybl.ws.commons.computation.service.ReportService; -import com.powsybl.ws.commons.computation.service.UuidGeneratorService; +import com.powsybl.ws.commons.computation.service.*; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.micrometer.observation.ObservationRegistry; @@ -47,9 +37,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @ExtendWith({ MockitoExtension.class }) @Slf4j @@ -307,4 +295,19 @@ void testComputationCancelFailed() { workerService.consumeCancel().accept(message); verify(notificationService.getPublisher(), times(1)).send(eq("publishCancelFailed-out-0"), isA(Message.class)); } + + @Test + void testComputationSuccessIfPostRunFails() { + // inits + initComputationExecution(); + runContext.setComputationResWanted(ComputationResultWanted.SUCCESS); + + doThrow(new PostRunException("Error occurred while sending reports")).when(reportService).sendReport(any(), any()); + + // execution / cleaning + workerService.consumeRun().accept(message); + + // test the course + verify(notificationService.getPublisher(), times(1)).send(eq("publishResult-out-0"), isA(Message.class)); + } }