diff --git a/src/main/java/org/gridsuite/modification/server/dto/ReportInfos.java b/src/main/java/org/gridsuite/modification/server/dto/ReportInfos.java index 4cb14ecbf..6fe8b9c30 100644 --- a/src/main/java/org/gridsuite/modification/server/dto/ReportInfos.java +++ b/src/main/java/org/gridsuite/modification/server/dto/ReportInfos.java @@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.UUID; @@ -16,10 +17,19 @@ * @author Slimane Amar */ @AllArgsConstructor +@NoArgsConstructor @Getter @Schema(description = "Report infos") public class ReportInfos { private UUID reportUuid; private UUID nodeUuid; + + private ReportMode reportMode; + + public ReportInfos(UUID reportUuid, UUID nodeUuid) { + this.reportUuid = reportUuid; + this.nodeUuid = nodeUuid; + this.reportMode = ReportMode.APPEND; + } } diff --git a/src/main/java/org/gridsuite/modification/server/dto/ReportMode.java b/src/main/java/org/gridsuite/modification/server/dto/ReportMode.java new file mode 100644 index 000000000..72ee3f877 --- /dev/null +++ b/src/main/java/org/gridsuite/modification/server/dto/ReportMode.java @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025, 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 org.gridsuite.modification.server.dto; + +/** + * @author Achour BERRAHMA + */ +public enum ReportMode { + APPEND, + REPLACE +} diff --git a/src/main/java/org/gridsuite/modification/server/modifications/NetworkModificationApplicator.java b/src/main/java/org/gridsuite/modification/server/modifications/NetworkModificationApplicator.java index ef7eea6b3..fe4e554ad 100644 --- a/src/main/java/org/gridsuite/modification/server/modifications/NetworkModificationApplicator.java +++ b/src/main/java/org/gridsuite/modification/server/modifications/NetworkModificationApplicator.java @@ -201,7 +201,11 @@ private ApplicationStatus apply(ModificationApplicationGroup modificationGroupIn .reduce(ApplicationStatus::max) .orElse(ApplicationStatus.ALL_OK); if (modificationGroupInfos.reportInfos().getReportUuid() != null) { - reportService.sendReport(modificationGroupInfos.reportInfos().getReportUuid(), reportNode); + reportService.sendReport( + modificationGroupInfos.reportInfos().getReportUuid(), + reportNode, + modificationGroupInfos.reportInfos().getReportMode() + ); } return groupApplicationStatus; } diff --git a/src/main/java/org/gridsuite/modification/server/service/ReportService.java b/src/main/java/org/gridsuite/modification/server/service/ReportService.java index 02a228070..c9cdda35f 100644 --- a/src/main/java/org/gridsuite/modification/server/service/ReportService.java +++ b/src/main/java/org/gridsuite/modification/server/service/ReportService.java @@ -13,6 +13,7 @@ import com.powsybl.commons.report.ReportNode; import com.powsybl.commons.report.ReportNodeDeserializer; import com.powsybl.commons.report.ReportNodeJsonModule; +import org.gridsuite.modification.server.dto.ReportMode; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -60,8 +61,9 @@ public void setReportServerRest(RestTemplate reportServerRest) { this.reportServerRest = Objects.requireNonNull(reportServerRest, "reportServerRest can't be null"); } - public void sendReport(UUID reportUuid, ReportNode reportNode) { - var path = UriComponentsBuilder.fromPath("{reportUuid}") + public void sendReport(UUID reportUuid, ReportNode reportNode, ReportMode reportMode) { + String endpoint = reportMode == ReportMode.REPLACE ? "replace" : ""; + var path = UriComponentsBuilder.fromPath("{reportUuid}" + (endpoint.isEmpty() ? "" : "/" + endpoint)) .buildAndExpand(reportUuid) .toUriString(); var headers = new HttpHeaders(); @@ -72,4 +74,8 @@ public void sendReport(UUID reportUuid, ReportNode reportNode) { throw new PowsyblException("error creating report", error); } } + + public void sendReport(UUID reportUuid, ReportNode reportNode) { + sendReport(reportUuid, reportNode, ReportMode.APPEND); + } } diff --git a/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java b/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java index c80ea253e..49dc91788 100644 --- a/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java +++ b/src/test/java/org/gridsuite/modification/server/VoltageInitReportTest.java @@ -15,11 +15,8 @@ import com.powsybl.iidm.network.ThreeSides; import lombok.extern.slf4j.Slf4j; import org.gridsuite.modification.dto.*; -import org.gridsuite.modification.server.dto.ModificationApplicationGroup; -import org.gridsuite.modification.server.dto.NetworkInfos; -import org.gridsuite.modification.server.dto.NetworkModificationResult; +import org.gridsuite.modification.server.dto.*; import org.gridsuite.modification.server.dto.NetworkModificationResult.ApplicationStatus; -import org.gridsuite.modification.server.dto.ReportInfos; import org.gridsuite.modification.server.entities.ModificationEntity; import org.gridsuite.modification.server.modifications.NetworkModificationApplicator; import org.gridsuite.modification.server.repositories.NetworkModificationRepository; @@ -47,6 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.verify; import static org.assertj.core.api.Assertions.assertThat; @@ -90,7 +88,7 @@ void testVoltageInitDuplicationLogs(final ApplicationStatus resultStatus, final // check produced report json data ArgumentCaptor reporterCaptor = ArgumentCaptor.forClass(ReportNode.class); - verify(reportService, atLeast(1)).sendReport(any(UUID.class), reporterCaptor.capture()); + verify(reportService, atLeast(1)).sendReport(any(UUID.class), reporterCaptor.capture(), eq(ReportMode.APPEND)); final ReportNode result = reporterCaptor.getValue(); assertNotNull(result); JSONAssert.assertEquals("voltage-init plan logs aggregated", diff --git a/src/test/java/org/gridsuite/modification/server/service/BuildTest.java b/src/test/java/org/gridsuite/modification/server/service/BuildTest.java index 223a21f2b..e87ac47be 100644 --- a/src/test/java/org/gridsuite/modification/server/service/BuildTest.java +++ b/src/test/java/org/gridsuite/modification/server/service/BuildTest.java @@ -140,7 +140,7 @@ class BuildTest { @Autowired private NetworkModificationApplicator networkModificationApplicator; - @Autowired + @MockitoSpyBean private ReportService reportService; @Autowired @@ -273,7 +273,7 @@ void runBuildForLineSplits(final MockWebServer server) throws Exception { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID, TEST_GROUP_ID_2)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1), new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_2))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE), new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_2, ReportMode.REPLACE))) .build(); mockMvc.perform(post(uriString, TEST_NETWORK_ID) .contentType(MediaType.APPLICATION_JSON) @@ -286,6 +286,8 @@ void runBuildForLineSplits(final MockWebServer server) throws Exception { Message buildMessage = output.receive(TIMEOUT, consumeBuildDestination); assertNotNull(buildMessage); assertEquals("me", buildMessage.getHeaders().get("receiver")); + ArgumentCaptor reporterCaptor = ArgumentCaptor.forClass(ReportNode.class); + verify(reportService, times(2)).sendReport(any(UUID.class), reporterCaptor.capture(), eq(ReportMode.REPLACE)); BuildInfos newBuildInfos = BuildInfos.builder() .originVariantId(NetworkCreation.VARIANT_ID) @@ -316,7 +318,7 @@ void runBuildWithEmptyGroupTest(final MockWebServer server) throws Exception { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE))) .build(); String expectedBody = mapper.writeValueAsString(ReportNode.newRootReportNode() .withResourceBundles("i18n.reports") @@ -427,7 +429,7 @@ void testIndexationAfterBuild(final MockWebServer server) { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE))) .build(); // Build variant @@ -715,7 +717,7 @@ void runBuildTest(final MockWebServer server) throws Exception { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID, TEST_GROUP_ID_2)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1), new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_2))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE), new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_2, ReportMode.REPLACE))) .build(); String buildInfosJson = objectWriter.writeValueAsString(buildInfos); mockMvc.perform(post(uriString, TEST_NETWORK_ID).contentType(MediaType.APPLICATION_JSON).content(buildInfosJson)) @@ -858,7 +860,7 @@ void runBuildWithStashedModificationsTest(final MockWebServer server) { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE))) .build(); networkModificationService.buildVariant(TEST_NETWORK_ID, buildInfos); @@ -885,7 +887,7 @@ void runBuildWithExcludedModificationsTest(final MockWebServer server) { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE))) .modificationUuidsToExclude(Map.of(TEST_GROUP_ID, Set.of(savedModificationEntities.get(1).getId()))) .build(); networkModificationService.buildVariant(TEST_NETWORK_ID, buildInfos); @@ -913,7 +915,7 @@ void stopBuildTest() throws Exception { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE))) .build(); String buildInfosJson = mapper.writeValueAsString(buildInfos); CompletableFuture.runAsync(() -> { @@ -1040,7 +1042,7 @@ void testBuildWithWorkflowInfos() throws Exception { .originVariantId(VariantManagerConstants.INITIAL_VARIANT_ID) .destinationVariantId(NetworkCreation.VARIANT_ID) .modificationGroupUuids(List.of(TEST_GROUP_ID, TEST_GROUP_ID_2)) - .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1), new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_2))) + .reportsInfos(List.of(new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_1, ReportMode.REPLACE), new ReportInfos(UUID.randomUUID(), TEST_SUB_REPORTER_ID_2, ReportMode.REPLACE))) .build(); String buildInfosJson = objectWriter.writeValueAsString(buildInfos); doNothing().when(notificationService).emitBuildMessage(any()); diff --git a/src/test/java/org/gridsuite/modification/server/utils/TestUtils.java b/src/test/java/org/gridsuite/modification/server/utils/TestUtils.java index a91593846..4f98bd04b 100644 --- a/src/test/java/org/gridsuite/modification/server/utils/TestUtils.java +++ b/src/test/java/org/gridsuite/modification/server/utils/TestUtils.java @@ -21,10 +21,7 @@ import mockwebserver3.MockWebServer; import org.apache.commons.text.StringSubstitutor; import org.gridsuite.modification.dto.ModificationInfos; -import org.gridsuite.modification.server.dto.ModificationApplicationContext; -import org.gridsuite.modification.server.dto.ModificationApplicationGroup; -import org.gridsuite.modification.server.dto.NetworkInfos; -import org.gridsuite.modification.server.dto.NetworkModificationResult; +import org.gridsuite.modification.server.dto.*; import org.gridsuite.modification.server.modifications.NetworkModificationApplicator; import org.gridsuite.modification.server.service.ReportService; import org.junit.platform.commons.util.StringUtils; @@ -144,7 +141,7 @@ public static String resourceToString(String resource) throws IOException { public static void assertLogNthMessage(String expectedMessage, String reportKey, ReportService reportService, int rank) { ArgumentCaptor reporterCaptor = ArgumentCaptor.forClass(ReportNode.class); - verify(reportService, atLeast(1)).sendReport(any(UUID.class), reporterCaptor.capture()); + verify(reportService, atLeast(1)).sendReport(any(UUID.class), reporterCaptor.capture(), eq(ReportMode.APPEND)); assertNotNull(reporterCaptor.getValue()); Optional message = getMessageFromReporter(reportKey, reporterCaptor.getValue(), rank); assertTrue(message.isPresent()); @@ -157,7 +154,7 @@ public static void assertLogMessage(String expectedMessage, String reportKey, Re public static void assertLogMessageWithoutRank(String expectedMessage, String reportKey, ReportService reportService) { ArgumentCaptor reporterCaptor = ArgumentCaptor.forClass(ReportNode.class); - verify(reportService, atLeast(1)).sendReport(any(UUID.class), reporterCaptor.capture()); + verify(reportService, atLeast(1)).sendReport(any(UUID.class), reporterCaptor.capture(), eq(ReportMode.APPEND)); assertNotNull(reporterCaptor.getValue()); assertTrue(assertMessageFoundFromReporter(expectedMessage, reportKey, reporterCaptor.getValue())); }