diff --git a/monitor-commons/src/main/java/org/gridsuite/monitor/commons/MessageType.java b/monitor-commons/src/main/java/org/gridsuite/monitor/commons/MessageType.java index 2a6eb2c..aed280f 100644 --- a/monitor-commons/src/main/java/org/gridsuite/monitor/commons/MessageType.java +++ b/monitor-commons/src/main/java/org/gridsuite/monitor/commons/MessageType.java @@ -11,5 +11,6 @@ */ public enum MessageType { EXECUTION_STATUS_UPDATE, - STEP_STATUS_UPDATE + STEP_STATUS_UPDATE, + STEPS_STATUSES_UPDATE, } diff --git a/monitor-commons/src/main/java/org/gridsuite/monitor/commons/StepStatus.java b/monitor-commons/src/main/java/org/gridsuite/monitor/commons/StepStatus.java index 42af03a..1c321d6 100644 --- a/monitor-commons/src/main/java/org/gridsuite/monitor/commons/StepStatus.java +++ b/monitor-commons/src/main/java/org/gridsuite/monitor/commons/StepStatus.java @@ -10,6 +10,7 @@ * @author Antoine Bouhours */ public enum StepStatus { + SCHEDULED, RUNNING, COMPLETED, FAILED, diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/MonitorController.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/MonitorController.java index d860674..d450879 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/MonitorController.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/controllers/MonitorController.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import org.gridsuite.monitor.commons.ProcessExecutionStep; import org.gridsuite.monitor.commons.ProcessType; import org.gridsuite.monitor.commons.SecurityAnalysisConfig; import org.gridsuite.monitor.server.dto.ProcessExecution; @@ -71,4 +72,14 @@ public ResponseEntity> getExecutionResults(@Parameter(description = public ResponseEntity> getLaunchedProcesses(@Parameter(description = "Process type") @RequestParam(name = "processType") ProcessType processType) { return ResponseEntity.ok(monitorService.getLaunchedProcesses(processType)); } + + @GetMapping("/executions/{executionId}/step-infos") + @Operation(summary = "Get execution steps statuses") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "The execution steps statuses"), + @ApiResponse(responseCode = "404", description = "execution id was not found")}) + public ResponseEntity> getStepsInfos(@Parameter(description = "Execution UUID") @PathVariable UUID executionId) { + return monitorService.getStepsInfos(executionId).map(list -> ResponseEntity.ok().body(list)) + .orElseGet(() -> ResponseEntity.notFound().build()); + } } diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionMapper.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionMapper.java index d0cae4c..8eb8f37 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionMapper.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionMapper.java @@ -8,14 +8,13 @@ import org.gridsuite.monitor.server.dto.ProcessExecution; import org.gridsuite.monitor.server.entities.ProcessExecutionEntity; -import org.springframework.stereotype.Component; /** * @author Franck Lecuyer */ -@Component +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class ProcessExecutionMapper { - public ProcessExecution toDto(ProcessExecutionEntity entity) { + public static ProcessExecution toDto(ProcessExecutionEntity entity) { return new ProcessExecution( entity.getId(), entity.getType(), diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionStepMapper.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionStepMapper.java new file mode 100644 index 0000000..b58db31 --- /dev/null +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/ProcessExecutionStepMapper.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2026, 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.monitor.server.mapper; + +import org.gridsuite.monitor.commons.ProcessExecutionStep; +import org.gridsuite.monitor.server.entities.ProcessExecutionStepEntity; + +/** + * @author Franck Lecuyer + */ +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") +public class ProcessExecutionStepMapper { + public static ProcessExecutionStep toDto(ProcessExecutionStepEntity entity) { + return new ProcessExecutionStep( + entity.getId(), + entity.getStepType(), + entity.getStepOrder(), + entity.getStatus(), + entity.getResultId(), + entity.getResultType(), + entity.getReportId(), + entity.getStartedAt(), + entity.getCompletedAt()); + } +} diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/SecurityAnalysisConfigMapper.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/SecurityAnalysisConfigMapper.java index 1b00ccd..0330f74 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/SecurityAnalysisConfigMapper.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/mapper/SecurityAnalysisConfigMapper.java @@ -8,23 +8,19 @@ import org.gridsuite.monitor.commons.SecurityAnalysisConfig; import org.gridsuite.monitor.server.entities.SecurityAnalysisConfigEntity; -import org.springframework.stereotype.Component; /** * @author Franck Lecuyer */ -@Component +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") public class SecurityAnalysisConfigMapper { - - public SecurityAnalysisConfigEntity toEntity(SecurityAnalysisConfig dto) { + public static SecurityAnalysisConfigEntity toEntity(SecurityAnalysisConfig dto) { SecurityAnalysisConfigEntity entity = new SecurityAnalysisConfigEntity(); - entity.setParametersUuid(dto.parametersUuid()); - entity.setContingencies(dto.contingencies()); - entity.setModificationUuids(dto.modificationUuids()); + update(entity, dto); return entity; } - public SecurityAnalysisConfig toDto(SecurityAnalysisConfigEntity entity) { + public static SecurityAnalysisConfig toDto(SecurityAnalysisConfigEntity entity) { return new SecurityAnalysisConfig( entity.getParametersUuid(), entity.getContingencies(), @@ -32,7 +28,7 @@ public SecurityAnalysisConfig toDto(SecurityAnalysisConfigEntity entity) { ); } - public void update(SecurityAnalysisConfigEntity entity, SecurityAnalysisConfig dto) { + public static void update(SecurityAnalysisConfigEntity entity, SecurityAnalysisConfig dto) { entity.setParametersUuid(dto.parametersUuid()); entity.setContingencies(dto.contingencies()); entity.setModificationUuids(dto.modificationUuids()); diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerService.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerService.java index 927396f..f2ea5fc 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerService.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerService.java @@ -19,6 +19,7 @@ import org.springframework.messaging.Message; import java.io.UncheckedIOException; +import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -53,6 +54,7 @@ public Consumer> consumeMonitorUpdate() { switch (messageType) { case EXECUTION_STATUS_UPDATE -> handleExecutionStatusUpdate(executionId, message); case STEP_STATUS_UPDATE -> handleStepStatusUpdate(executionId, message); + case STEPS_STATUSES_UPDATE -> handleStepsStatusesUpdate(executionId, message); default -> LOGGER.warn("Unknown message type: {}", messageType); } }; @@ -68,6 +70,11 @@ private void handleStepStatusUpdate(UUID executionId, Message message) { monitorService.updateStepStatus(executionId, processExecutionStep); } + private void handleStepsStatusesUpdate(UUID executionId, Message message) { + List processExecutionSteps = parsePayload(message.getPayload(), List.class); + monitorService.updateStepsStatuses(executionId, processExecutionSteps); + } + private T parsePayload(String payload, Class clazz) { try { return objectMapper.readValue(payload, clazz); diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java index 467197a..45ac6d4 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/MonitorService.java @@ -17,12 +17,14 @@ import org.gridsuite.monitor.server.entities.ProcessExecutionEntity; import org.gridsuite.monitor.server.entities.ProcessExecutionStepEntity; import org.gridsuite.monitor.server.mapper.ProcessExecutionMapper; +import org.gridsuite.monitor.server.mapper.ProcessExecutionStepMapper; import org.gridsuite.monitor.server.repositories.ProcessExecutionRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.Instant; import java.util.List; +import java.util.Optional; import java.util.UUID; /** @@ -36,7 +38,6 @@ public class MonitorService { private final NotificationService notificationService; private final ReportService reportService; private final ResultService resultService; - private final ProcessExecutionMapper processExecutionMapper; @Transactional public UUID executeProcess(UUID caseUuid, String userId, ProcessConfig processConfig) { @@ -71,25 +72,45 @@ public void updateExecutionStatus(UUID executionId, ProcessStatus status, String }); } + private void updateStep(ProcessExecutionEntity execution, ProcessExecutionStepEntity stepEntity) { + List steps = Optional.ofNullable(execution.getSteps()).orElseGet(() -> { + List newSteps = new java.util.ArrayList<>(); + execution.setSteps(newSteps); + return newSteps; + }); + steps.stream() + .filter(s -> s.getId().equals(stepEntity.getId())) + .findFirst() + .ifPresentOrElse( + existingStep -> { + existingStep.setStatus(stepEntity.getStatus()); + existingStep.setStepType(stepEntity.getStepType()); + existingStep.setStepOrder(stepEntity.getStepOrder()); + existingStep.setStartedAt(stepEntity.getStartedAt()); + existingStep.setCompletedAt(stepEntity.getCompletedAt()); + existingStep.setResultId(stepEntity.getResultId()); + existingStep.setResultType(stepEntity.getResultType()); + existingStep.setReportId(stepEntity.getReportId()); + }, + () -> steps.add(stepEntity)); + } + @Transactional public void updateStepStatus(UUID executionId, ProcessExecutionStep processExecutionStep) { executionRepository.findById(executionId).ifPresent(execution -> { ProcessExecutionStepEntity stepEntity = toStepEntity(processExecutionStep); - execution.getSteps().stream() - .filter(s -> s.getId().equals(stepEntity.getId())) - .findFirst() - .ifPresentOrElse( - existingStep -> { - existingStep.setStatus(stepEntity.getStatus()); - existingStep.setStepType(stepEntity.getStepType()); - existingStep.setStepOrder(stepEntity.getStepOrder()); - existingStep.setStartedAt(stepEntity.getStartedAt()); - existingStep.setCompletedAt(stepEntity.getCompletedAt()); - existingStep.setResultId(stepEntity.getResultId()); - existingStep.setResultType(stepEntity.getResultType()); - existingStep.setReportId(stepEntity.getReportId()); - }, - () -> execution.getSteps().add(stepEntity)); + updateStep(execution, stepEntity); + executionRepository.save(execution); + }); + } + + @Transactional + public void updateStepsStatuses(UUID executionId, List processExecutionSteps) { + executionRepository.findById(executionId).ifPresent(execution -> { + processExecutionSteps.forEach(processExecutionStep -> { + ProcessExecutionStepEntity stepEntity = toStepEntity(processExecutionStep); + updateStep(execution, stepEntity); + }); executionRepository.save(execution); }); } @@ -118,7 +139,7 @@ public List getReports(UUID executionId) { private List getReportIds(UUID executionId) { return executionRepository.findById(executionId) - .map(execution -> execution.getSteps().stream() + .map(execution -> Optional.ofNullable(execution.getSteps()).orElse(List.of()).stream() .map(ProcessExecutionStepEntity::getReportId) .filter(java.util.Objects::nonNull) .toList()) @@ -135,7 +156,7 @@ public List getResults(UUID executionId) { private List getResultInfos(UUID executionId) { return executionRepository.findById(executionId) - .map(execution -> execution.getSteps().stream() + .map(execution -> Optional.ofNullable(execution.getSteps()).orElse(List.of()).stream() .filter(step -> step.getResultId() != null) .map(step -> new ResultInfos(step.getResultId(), step.getResultType())) .toList()) @@ -145,6 +166,18 @@ private List getResultInfos(UUID executionId) { @Transactional(readOnly = true) public List getLaunchedProcesses(ProcessType processType) { return executionRepository.findByTypeAndStartedAtIsNotNullOrderByStartedAtDesc(processType.name()).stream() - .map(processExecutionMapper::toDto).toList(); + .map(ProcessExecutionMapper::toDto).toList(); + } + + @Transactional(readOnly = true) + public Optional> getStepsInfos(UUID executionId) { + Optional entity = executionRepository.findById(executionId); + if (entity.isPresent()) { + return entity.map(execution -> Optional.ofNullable(execution.getSteps()).orElse(List.of()).stream() + .map(ProcessExecutionStepMapper::toDto) + .toList()); + } else { + return Optional.empty(); + } } } diff --git a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ProcessConfigService.java b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ProcessConfigService.java index de235b8..22ea3a7 100644 --- a/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ProcessConfigService.java +++ b/monitor-server/src/main/java/org/gridsuite/monitor/server/services/ProcessConfigService.java @@ -25,17 +25,14 @@ public class ProcessConfigService { private final ProcessConfigRepository processConfigRepository; - private final SecurityAnalysisConfigMapper securityAnalysisConfigMapper; - - public ProcessConfigService(ProcessConfigRepository processConfigRepository, SecurityAnalysisConfigMapper securityAnalysisConfigMapper) { + public ProcessConfigService(ProcessConfigRepository processConfigRepository) { this.processConfigRepository = processConfigRepository; - this.securityAnalysisConfigMapper = securityAnalysisConfigMapper; } @Transactional public UUID createProcessConfig(ProcessConfig processConfig) { AbstractProcessConfigEntity entity = switch (processConfig) { - case SecurityAnalysisConfig sac -> securityAnalysisConfigMapper.toEntity(sac); + case SecurityAnalysisConfig sac -> SecurityAnalysisConfigMapper.toEntity(sac); default -> throw new IllegalArgumentException("Unsupported process config type: " + processConfig.processType()); }; return processConfigRepository.save(entity).getId(); @@ -45,7 +42,7 @@ public UUID createProcessConfig(ProcessConfig processConfig) { public Optional getProcessConfig(UUID processConfigUuid) { return processConfigRepository.findById(processConfigUuid).flatMap(entity -> switch (entity) { case SecurityAnalysisConfigEntity sae -> - Optional.of((ProcessConfig) securityAnalysisConfigMapper.toDto(sae)); + Optional.of((ProcessConfig) SecurityAnalysisConfigMapper.toDto(sae)); default -> throw new IllegalArgumentException("Unsupported entity type: " + entity.getType()); }); } @@ -59,7 +56,7 @@ public boolean updateProcessConfig(UUID processConfigUuid, ProcessConfig process } switch (processConfig) { case SecurityAnalysisConfig sac -> - securityAnalysisConfigMapper.update((SecurityAnalysisConfigEntity) entity, sac); + SecurityAnalysisConfigMapper.update((SecurityAnalysisConfigEntity) entity, sac); default -> throw new IllegalArgumentException("Unsupported process config type: " + processConfig.processType()); } return true; diff --git a/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/MonitorControllerTest.java b/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/MonitorControllerTest.java index 3034885..66adb07 100644 --- a/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/MonitorControllerTest.java +++ b/monitor-server/src/test/java/org/gridsuite/monitor/server/controllers/MonitorControllerTest.java @@ -7,9 +7,11 @@ package org.gridsuite.monitor.server.controllers; import com.fasterxml.jackson.databind.ObjectMapper; +import org.gridsuite.monitor.commons.ProcessExecutionStep; +import org.gridsuite.monitor.commons.SecurityAnalysisConfig; +import org.gridsuite.monitor.commons.StepStatus; import org.gridsuite.monitor.commons.ProcessStatus; import org.gridsuite.monitor.commons.ProcessType; -import org.gridsuite.monitor.commons.SecurityAnalysisConfig; import org.gridsuite.monitor.server.dto.ProcessExecution; import org.gridsuite.monitor.server.dto.ReportLog; import org.gridsuite.monitor.server.dto.ReportPage; @@ -24,6 +26,7 @@ import java.time.Instant; import java.util.List; +import java.util.Optional; import java.util.UUID; import static org.hamcrest.Matchers.hasSize; @@ -150,4 +153,34 @@ void getLaunchedProcesses() throws Exception { verify(monitorService).getLaunchedProcesses(ProcessType.SECURITY_ANALYSIS); } + + @Test + void getStepsInfos() throws Exception { + UUID executionId = UUID.randomUUID(); + ProcessExecutionStep processExecutionStep1 = new ProcessExecutionStep(UUID.randomUUID(), "loadNetwork", 0, StepStatus.RUNNING, null, null, UUID.randomUUID(), Instant.now(), null); + ProcessExecutionStep processExecutionStep2 = new ProcessExecutionStep(UUID.randomUUID(), "applyModifs", 1, StepStatus.SCHEDULED, null, null, UUID.randomUUID(), null, null); + ProcessExecutionStep processExecutionStep3 = new ProcessExecutionStep(UUID.randomUUID(), "runSA", 2, StepStatus.SCHEDULED, null, null, UUID.randomUUID(), null, null); + List processExecutionStepList = List.of(processExecutionStep1, processExecutionStep2, processExecutionStep3); + + when(monitorService.getStepsInfos(executionId)).thenReturn(Optional.of(processExecutionStepList)); + + mockMvc.perform(get("/v1/executions/{executionId}/step-infos", executionId)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$", hasSize(3))) + .andExpect(content().json(objectMapper.writeValueAsString(processExecutionStepList))); + + verify(monitorService).getStepsInfos(executionId); + } + + @Test + void getStepsInfosShouldReturn404WhenExecutionNotFound() throws Exception { + UUID executionId = UUID.randomUUID(); + when(monitorService.getStepsInfos(executionId)).thenReturn(Optional.empty()); + + mockMvc.perform(get("/v1/executions/{executionId}/step-infos", executionId)) + .andExpect(status().isNotFound()); + + verify(monitorService).getStepsInfos(executionId); + } } diff --git a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ConsumerServiceTest.java b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ConsumerServiceTest.java index dae001f..ac13844 100644 --- a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ConsumerServiceTest.java +++ b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ConsumerServiceTest.java @@ -20,6 +20,7 @@ import java.io.UncheckedIOException; import java.time.Instant; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Consumer; @@ -120,4 +121,35 @@ void consumeProcessExecutionStepUpdateMessage() throws JsonProcessingException { verify(monitorService).updateStepStatus(eq(executionId), any(ProcessExecutionStep.class)); verify(monitorService, never()).updateExecutionStatus(any(), any(), any(), any(), any()); } + + @Test + void consumeProcessExecutionStepsUpdateMessage() throws JsonProcessingException { + UUID executionId = UUID.randomUUID(); + UUID stepId1 = UUID.randomUUID(); + UUID stepId2 = UUID.randomUUID(); + ProcessExecutionStep stepUpdate1 = ProcessExecutionStep.builder() + .id(stepId1) + .stepType("LOAD_NETWORK") + .status(StepStatus.SCHEDULED) + .startedAt(Instant.now()) + .build(); + ProcessExecutionStep stepUpdate2 = ProcessExecutionStep.builder() + .id(stepId2) + .stepType("SECURITY_ANALYSIS") + .status(StepStatus.SCHEDULED) + .startedAt(Instant.now()) + .build(); + String payload = objectMapper.writeValueAsString(List.of(stepUpdate1, stepUpdate2)); + Map headers = new HashMap<>(); + headers.put(ConsumerService.HEADER_MESSAGE_TYPE, MessageType.STEPS_STATUSES_UPDATE.toString()); + headers.put(ConsumerService.HEADER_EXECUTION_ID, executionId.toString()); + Message message = new GenericMessage<>(payload, headers); + Consumer> consumer = consumerService.consumeMonitorUpdate(); + + consumer.accept(message); + + verify(monitorService).updateStepsStatuses(eq(executionId), any(List.class)); + verify(monitorService, never()).updateStepStatus(any(), any()); + verify(monitorService, never()).updateExecutionStatus(any(), any(), any(), any(), any()); + } } diff --git a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java index d8a2270..0fa31f1 100644 --- a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java +++ b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/MonitorServiceTest.java @@ -13,14 +13,12 @@ import org.gridsuite.monitor.server.dto.Severity; import org.gridsuite.monitor.server.entities.ProcessExecutionEntity; import org.gridsuite.monitor.server.entities.ProcessExecutionStepEntity; -import org.gridsuite.monitor.server.mapper.ProcessExecutionMapper; import org.gridsuite.monitor.server.repositories.ProcessExecutionRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import java.time.Instant; @@ -54,9 +52,6 @@ class MonitorServiceTest { @InjectMocks private MonitorService monitorService; - @Spy - private ProcessExecutionMapper processExecutionMapper; - private SecurityAnalysisConfig securityAnalysisConfig; private UUID caseUuid; private UUID executionId; @@ -250,6 +245,89 @@ void updateStepStatusShouldUpdateExistingStep() { verify(executionRepository).save(execution); } + @Test + void updateStepsStatusesShouldUpdateExistingSteps() { + UUID stepId1 = UUID.randomUUID(); + UUID stepId2 = UUID.randomUUID(); + UUID originalResultId1 = UUID.randomUUID(); + UUID originalResultId2 = UUID.randomUUID(); + UUID newResultId1 = UUID.randomUUID(); + UUID newResultId2 = UUID.randomUUID(); + UUID newReportId1 = UUID.randomUUID(); + UUID newReportId2 = UUID.randomUUID(); + Instant startedAt1 = Instant.now().minusSeconds(60); + Instant startedAt2 = Instant.now().minusSeconds(40); + Instant completedAt1 = Instant.now(); + Instant completedAt2 = Instant.now(); + + ProcessExecutionStepEntity existingStep1 = ProcessExecutionStepEntity.builder() + .id(stepId1) + .stepType("LOAD_NETWORK") + .status(StepStatus.RUNNING) + .resultId(originalResultId1) + .startedAt(startedAt1) + .build(); + ProcessExecutionStepEntity existingStep2 = ProcessExecutionStepEntity.builder() + .id(stepId2) + .stepType("LOAD_FLOW") + .status(StepStatus.RUNNING) + .resultId(originalResultId2) + .startedAt(startedAt2) + .build(); + ProcessExecutionEntity execution = ProcessExecutionEntity.builder() + .id(executionId) + .type(ProcessType.SECURITY_ANALYSIS.name()) + .caseUuid(caseUuid) + .userId(userId) + .status(ProcessStatus.RUNNING) + .steps(new ArrayList<>(List.of(existingStep1, existingStep2))) + .build(); + when(executionRepository.findById(executionId)).thenReturn(Optional.of(execution)); + ProcessExecutionStep updateDto1 = ProcessExecutionStep.builder() + .id(stepId1) + .stepType("LOAD_NETWORK_UPDATED") + .status(StepStatus.COMPLETED) + .resultId(newResultId1) + .resultType(ResultType.SECURITY_ANALYSIS) + .reportId(newReportId1) + .startedAt(startedAt1) + .completedAt(completedAt1) + .build(); + ProcessExecutionStep updateDto2 = ProcessExecutionStep.builder() + .id(stepId2) + .stepType("LOAD_FLOW_UPDATED") + .status(StepStatus.COMPLETED) + .resultId(newResultId2) + .resultType(ResultType.SECURITY_ANALYSIS) + .reportId(newReportId2) + .startedAt(startedAt2) + .completedAt(completedAt2) + .build(); + monitorService.updateStepsStatuses(executionId, List.of(updateDto1, updateDto2)); + + verify(executionRepository).findById(executionId); + assertThat(execution.getSteps()).hasSize(2); + ProcessExecutionStepEntity updatedStep1 = execution.getSteps().get(0); + assertThat(updatedStep1.getId()).isEqualTo(stepId1); + assertThat(updatedStep1.getStepType()).isEqualTo("LOAD_NETWORK_UPDATED"); + assertThat(updatedStep1.getStatus()).isEqualTo(StepStatus.COMPLETED); + assertThat(updatedStep1.getResultId()).isEqualTo(newResultId1); + assertThat(updatedStep1.getResultType()).isEqualTo(ResultType.SECURITY_ANALYSIS); + assertThat(updatedStep1.getReportId()).isEqualTo(newReportId1); + assertThat(updatedStep1.getCompletedAt()).isEqualTo(completedAt1); + + ProcessExecutionStepEntity updatedStep2 = execution.getSteps().get(1); + assertThat(updatedStep2.getId()).isEqualTo(stepId2); + assertThat(updatedStep2.getStepType()).isEqualTo("LOAD_FLOW_UPDATED"); + assertThat(updatedStep2.getStatus()).isEqualTo(StepStatus.COMPLETED); + assertThat(updatedStep2.getResultId()).isEqualTo(newResultId2); + assertThat(updatedStep2.getResultType()).isEqualTo(ResultType.SECURITY_ANALYSIS); + assertThat(updatedStep2.getReportId()).isEqualTo(newReportId2); + assertThat(updatedStep2.getCompletedAt()).isEqualTo(completedAt2); + + verify(executionRepository).save(execution); + } + @Test void getReportsShouldReturnReports() { UUID reportId1 = UUID.randomUUID(); @@ -367,4 +445,56 @@ void getLaunchedProcesses() { assertThat(result).hasSize(2).containsExactly(processExecution2, processExecution1); verify(executionRepository).findByTypeAndStartedAtIsNotNullOrderByStartedAtDesc(ProcessType.SECURITY_ANALYSIS.name()); } + + @Test + void getStepsInfos() { + UUID executionUuid = UUID.randomUUID(); + UUID stepId1 = UUID.randomUUID(); + UUID stepId2 = UUID.randomUUID(); + Instant startedAt1 = Instant.now(); + ProcessExecutionEntity execution = ProcessExecutionEntity.builder() + .id(executionUuid) + .type(ProcessType.SECURITY_ANALYSIS.name()) + .steps(List.of(ProcessExecutionStepEntity.builder().id(stepId1).stepType("loadNetwork").stepOrder(0).status(StepStatus.RUNNING).startedAt(startedAt1).build(), + ProcessExecutionStepEntity.builder().id(stepId2).stepType("applyModifs").stepOrder(1).status(StepStatus.SCHEDULED).build())) + .build(); + + when(executionRepository.findById(executionUuid)).thenReturn(Optional.of(execution)); + + Optional> result = monitorService.getStepsInfos(executionUuid); + + ProcessExecutionStep processExecutionStep1 = new ProcessExecutionStep(stepId1, "loadNetwork", 0, StepStatus.RUNNING, null, null, null, startedAt1, null); + ProcessExecutionStep processExecutionStep2 = new ProcessExecutionStep(stepId2, "applyModifs", 1, StepStatus.SCHEDULED, null, null, null, null, null); + + assertThat(result).isPresent(); + assertThat(result.get()).hasSize(2).containsExactly(processExecutionStep1, processExecutionStep2); + verify(executionRepository).findById(executionUuid); + } + + @Test + void getStepsInfosShouldReturnEmptyWhenExecutionNotFound() { + UUID executionUuid = UUID.randomUUID(); + when(executionRepository.findById(executionUuid)).thenReturn(Optional.empty()); + + Optional> result = monitorService.getStepsInfos(executionUuid); + + assertThat(result).isEmpty(); + verify(executionRepository).findById(executionUuid); + } + + @Test + void getStepsInfosShouldReturnEmptyListWhenNoSteps() { + UUID executionUuid = UUID.randomUUID(); + ProcessExecutionEntity execution = ProcessExecutionEntity.builder() + .id(executionUuid) + .type(ProcessType.SECURITY_ANALYSIS.name()) + .steps(null) + .build(); + when(executionRepository.findById(executionUuid)).thenReturn(Optional.of(execution)); + + Optional> result = monitorService.getStepsInfos(executionUuid); + + assertThat(result).isPresent(); + assertThat(result.get()).isEmpty(); + } } diff --git a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ProcessConfigServiceTest.java b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ProcessConfigServiceTest.java index b9833b5..284fd0f 100644 --- a/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ProcessConfigServiceTest.java +++ b/monitor-server/src/test/java/org/gridsuite/monitor/server/services/ProcessConfigServiceTest.java @@ -18,7 +18,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; @@ -46,9 +45,6 @@ class ProcessConfigServiceTest { private SecurityAnalysisConfig securityAnalysisConfig; - @Spy - private SecurityAnalysisConfigMapper securityAnalysisConfigMapper; - @BeforeEach void setUp() { securityAnalysisConfig = new SecurityAnalysisConfig( @@ -85,7 +81,7 @@ void createSecurityAnalysisConfig() { @Test void getSecurityAnalysisConfig() { UUID processConfigId = UUID.randomUUID(); - SecurityAnalysisConfigEntity securityAnalysisConfigEntity = securityAnalysisConfigMapper.toEntity(securityAnalysisConfig); + SecurityAnalysisConfigEntity securityAnalysisConfigEntity = SecurityAnalysisConfigMapper.toEntity(securityAnalysisConfig); when(processConfigRepository.findById(processConfigId)).thenReturn(Optional.of(securityAnalysisConfigEntity)); @@ -109,7 +105,7 @@ void getSecurityAnalysisConfigNotFound() { @Test void updateSecurityAnalysisConfig() { UUID processConfigId = UUID.randomUUID(); - SecurityAnalysisConfigEntity securityAnalysisConfigEntity = securityAnalysisConfigMapper.toEntity(securityAnalysisConfig); + SecurityAnalysisConfigEntity securityAnalysisConfigEntity = SecurityAnalysisConfigMapper.toEntity(securityAnalysisConfig); SecurityAnalysisConfig newSecurityAnalysisConfig = new SecurityAnalysisConfig( UUID.randomUUID(), diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcess.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcess.java index dfbb355..9b1a719 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcess.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcess.java @@ -55,8 +55,6 @@ public void execute(ProcessExecutionContext context) { } } - protected abstract List> defineSteps(); - protected void handleStepFailure(ProcessExecutionContext context, ProcessStep step, Exception e) { //TODO better error handling LOGGER.error("Execution id: {} - Step failed: {} - {}", context.getExecutionId(), step.getType(), e.getMessage()); diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcessStep.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcessStep.java index 1f163dc..2671026 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcessStep.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/AbstractProcessStep.java @@ -9,6 +9,8 @@ import lombok.Getter; import org.gridsuite.monitor.commons.ProcessConfig; +import java.util.UUID; + /** * @author Antoine Bouhours */ @@ -16,8 +18,10 @@ public abstract class AbstractProcessStep implements ProcessStep { private final ProcessStepType type; + private final UUID id; protected AbstractProcessStep(ProcessStepType type) { this.type = type; + this.id = UUID.randomUUID(); } } diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/Process.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/Process.java index 84e7174..0959f0b 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/Process.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/Process.java @@ -9,6 +9,8 @@ import org.gridsuite.monitor.commons.ProcessConfig; import org.gridsuite.monitor.commons.ProcessType; +import java.util.List; + /** * @author Antoine Bouhours */ @@ -17,4 +19,6 @@ public interface Process { ProcessType getProcessType(); void execute(ProcessExecutionContext context); + + List> defineSteps(); } diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessExecutionContext.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessExecutionContext.java index 1d150fa..e4c64f3 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessExecutionContext.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessExecutionContext.java @@ -34,6 +34,6 @@ public ProcessExecutionContext(UUID executionId, UUID caseUuid, C config, String } public ProcessStepExecutionContext createStepContext(ProcessStep step, int stepOrder) { - return new ProcessStepExecutionContext<>(this, step.getType(), stepOrder); + return new ProcessStepExecutionContext<>(this, step.getType(), step.getId(), stepOrder); } } diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStep.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStep.java index 652bebb..2dbe815 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStep.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStep.java @@ -8,6 +8,8 @@ import org.gridsuite.monitor.commons.ProcessConfig; +import java.util.UUID; + /** * @author Antoine Bouhours */ @@ -15,6 +17,7 @@ public interface ProcessStep { ProcessStepType getType(); - void execute(ProcessStepExecutionContext context); + UUID getId(); + void execute(ProcessStepExecutionContext context); } diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContext.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContext.java index 199499e..29e4481 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContext.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContext.java @@ -25,7 +25,7 @@ public class ProcessStepExecutionContext { private final ProcessExecutionContext processContext; @Getter - private final UUID stepExecutionId = UUID.randomUUID(); + private final UUID stepExecutionId; @Getter private final int stepOrder; @Getter @@ -39,8 +39,9 @@ public class ProcessStepExecutionContext { @Setter private ResultInfos resultInfos; - public ProcessStepExecutionContext(ProcessExecutionContext processContext, ProcessStepType processStepType, int stepOrder) { + public ProcessStepExecutionContext(ProcessExecutionContext processContext, ProcessStepType processStepType, UUID stepId, int stepOrder) { this.processContext = processContext; + this.stepExecutionId = stepId; this.processStepType = processStepType; this.reportInfos = new ReportInfos(UUID.randomUUID(), ReportNode.newRootReportNode() .withAllResourceBundlesFromClasspath() diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/securityanalysis/SecurityAnalysisProcess.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/securityanalysis/SecurityAnalysisProcess.java index 844af21..0e80ed7 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/securityanalysis/SecurityAnalysisProcess.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/processes/securityanalysis/SecurityAnalysisProcess.java @@ -40,7 +40,7 @@ public SecurityAnalysisProcess( } @Override - protected List> defineSteps() { + public List> defineSteps() { return List.of( loadNetworkStep, applyModificationsStep, diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/NotificationService.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/NotificationService.java index 93ac742..61b6c6e 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/NotificationService.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/NotificationService.java @@ -14,6 +14,7 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.stereotype.Service; +import java.util.List; import java.util.UUID; /** @@ -60,4 +61,12 @@ public void updateStepStatus(UUID executionId, ProcessExecutionStep processExecu processExecutionStep ); } + + public void updateStepsStatuses(UUID executionId, List processExecutionSteps) { + sendMonitorUpdate( + executionId, + MessageType.STEPS_STATUSES_UPDATE, + processExecutionSteps + ); + } } diff --git a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionService.java b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionService.java index ddaf8ae..38b8c78 100644 --- a/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionService.java +++ b/monitor-worker-server/src/main/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionService.java @@ -8,11 +8,14 @@ import org.gridsuite.monitor.commons.ProcessConfig; import org.gridsuite.monitor.commons.ProcessExecutionStatusUpdate; +import org.gridsuite.monitor.commons.ProcessExecutionStep; import org.gridsuite.monitor.commons.ProcessRunMessage; import org.gridsuite.monitor.commons.ProcessStatus; import org.gridsuite.monitor.commons.ProcessType; +import org.gridsuite.monitor.commons.StepStatus; import org.gridsuite.monitor.worker.server.core.Process; import org.gridsuite.monitor.worker.server.core.ProcessExecutionContext; +import org.gridsuite.monitor.worker.server.core.ProcessStep; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -21,6 +24,7 @@ import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * @author Antoine Bouhours @@ -55,9 +59,19 @@ public void executeProcess(ProcessRunMessage runMes executionEnvName ); - updateExecutionStatus(context.getExecutionId(), context.getExecutionEnvName(), ProcessStatus.RUNNING); + try { + List> steps = process.defineSteps(); + notificationService.updateStepsStatuses(context.getExecutionId(), + IntStream.range(0, steps.size()) + .mapToObj(i -> new ProcessExecutionStep(steps.get(i).getId(), steps.get(i).getType().getName(), i, StepStatus.SCHEDULED, null, null, null, null, null)) + .toList()); + } catch (Exception e) { + updateExecutionStatus(context.getExecutionId(), context.getExecutionEnvName(), ProcessStatus.FAILED); + throw e; + } try { + updateExecutionStatus(context.getExecutionId(), context.getExecutionEnvName(), ProcessStatus.RUNNING); process.execute(context); updateExecutionStatus(context.getExecutionId(), context.getExecutionEnvName(), ProcessStatus.COMPLETED); } catch (Exception e) { diff --git a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContextTest.java b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContextTest.java index 15b0ed6..7dd80ef 100644 --- a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContextTest.java +++ b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessStepExecutionContextTest.java @@ -43,15 +43,16 @@ void shouldInitializeCorrectly() { int stepOrder = 2; UUID executionId = UUID.randomUUID(); UUID caseUuid = UUID.randomUUID(); + UUID stepExecutionId = UUID.randomUUID(); when(stepType.getName()).thenReturn("test-step"); when(processContext.getExecutionId()).thenReturn(executionId); when(processContext.getCaseUuid()).thenReturn(caseUuid); when(processContext.getNetwork()).thenReturn(network); when(processContext.getConfig()).thenReturn(config); - ProcessStepExecutionContext stepContext = new ProcessStepExecutionContext<>(processContext, stepType, stepOrder); + ProcessStepExecutionContext stepContext = new ProcessStepExecutionContext<>(processContext, stepType, stepExecutionId, stepOrder); - assertThat(stepContext.getStepExecutionId()).isNotNull(); + assertThat(stepContext.getStepExecutionId()).isEqualTo(stepExecutionId); assertThat(stepContext.getStepOrder()).isEqualTo(stepOrder); assertThat(stepContext.getNetwork()).isEqualTo(processContext.getNetwork()); assertThat(stepContext.getProcessExecutionId()).isEqualTo(processContext.getExecutionId()); @@ -68,8 +69,9 @@ void shouldInitializeCorrectly() { @Test void stepExecutionContextShouldSetAndGetFromParentExecutionContext() { int stepOrder = 1; + UUID stepId = UUID.randomUUID(); when(stepType.getName()).thenReturn("test-step"); - ProcessStepExecutionContext stepContext = new ProcessStepExecutionContext<>(processContext, stepType, stepOrder); + ProcessStepExecutionContext stepContext = new ProcessStepExecutionContext<>(processContext, stepType, stepId, stepOrder); Network newNetwork = mock(Network.class); stepContext.setNetwork(newNetwork); diff --git a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessTest.java b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessTest.java index ae655cb..cfb5b9e 100644 --- a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessTest.java +++ b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/core/ProcessTest.java @@ -99,7 +99,7 @@ public TestProcess(StepExecutionService stepExecutionService) { } @Override - protected List> defineSteps() { + public List> defineSteps() { // Return 3 dummy steps for testing ProcessStep step1 = mock(ProcessStep.class); ProcessStep step2 = mock(ProcessStep.class); diff --git a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/NotificationServiceTest.java b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/NotificationServiceTest.java index 00eb61e..87bf06c 100644 --- a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/NotificationServiceTest.java +++ b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/NotificationServiceTest.java @@ -17,6 +17,7 @@ import org.springframework.cloud.stream.function.StreamBridge; import org.springframework.messaging.Message; +import java.util.List; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -75,4 +76,22 @@ void updateStepStatusShouldSendStepStatusUpdateMessage() { }) ); } + + @Test + void updateStepsStatusesShouldSendStepStatusUpdateMessage() { + UUID executionId = UUID.randomUUID(); + List payload = List.of(new ProcessExecutionStep(), new ProcessExecutionStep()); + + notificationService.updateStepsStatuses(executionId, payload); + + verify(streamBridge).send( + eq("publishMonitorUpdate-out-0"), + argThat((Message message) -> { + assertThat(message.getPayload()).isSameAs(payload); + assertThat(message.getHeaders()).containsEntry(NotificationService.HEADER_MESSAGE_TYPE, MessageType.STEPS_STATUSES_UPDATE); + assertThat(message.getHeaders()).containsEntry(NotificationService.HEADER_EXECUTION_ID, executionId.toString()); + return true; + }) + ); + } } diff --git a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionServiceTest.java b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionServiceTest.java index 213768a..c4cc51a 100644 --- a/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionServiceTest.java +++ b/monitor-worker-server/src/test/java/org/gridsuite/monitor/worker/server/services/ProcessExecutionServiceTest.java @@ -11,8 +11,13 @@ import org.gridsuite.monitor.commons.ProcessRunMessage; import org.gridsuite.monitor.commons.ProcessStatus; import org.gridsuite.monitor.commons.ProcessType; +import org.gridsuite.monitor.commons.SecurityAnalysisConfig; +import org.gridsuite.monitor.commons.StepStatus; import org.gridsuite.monitor.worker.server.core.Process; import org.gridsuite.monitor.worker.server.core.ProcessExecutionContext; +import org.gridsuite.monitor.worker.server.processes.commons.steps.ApplyModificationsStep; +import org.gridsuite.monitor.worker.server.processes.commons.steps.LoadNetworkStep; +import org.gridsuite.monitor.worker.server.processes.securityanalysis.steps.SecurityAnalysisRunComputationStep; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -42,8 +47,29 @@ class ProcessExecutionServiceTest { @Mock private ProcessConfig processConfig; + @Mock + private NetworkConversionService networkConversionService; + + @Mock + private NetworkModificationService networkModificationService; + + @Mock + private NetworkModificationRestService networkModificationRestService; + + @Mock + private FilterService filterService; + + @Mock + private SecurityAnalysisService securityAnalysisService; + private ProcessExecutionService processExecutionService; + private LoadNetworkStep loadNetworkStep; + + private ApplyModificationsStep applyModificationsStep; + + private SecurityAnalysisRunComputationStep runComputationStep; + private static final String EXECUTION_ENV_NAME = "test-env"; @BeforeEach @@ -52,6 +78,10 @@ void setUp() { List> processList = List.of(process); processExecutionService = new ProcessExecutionService(processList, notificationService, EXECUTION_ENV_NAME); + + loadNetworkStep = new LoadNetworkStep<>(networkConversionService); + applyModificationsStep = new ApplyModificationsStep<>(networkModificationService, networkModificationRestService, filterService); + runComputationStep = new SecurityAnalysisRunComputationStep(securityAnalysisService); } @Test @@ -61,9 +91,27 @@ void executeProcessShouldCompleteSuccessfullyWhenProcessExecutesWithoutError() { when(processConfig.processType()).thenReturn(ProcessType.SECURITY_ANALYSIS); doNothing().when(process).execute(any(ProcessExecutionContext.class)); ProcessRunMessage runMessage = new ProcessRunMessage<>(executionId, caseUuid, processConfig); + when(process.defineSteps()).thenReturn((List) List.of(loadNetworkStep, applyModificationsStep, runComputationStep)); processExecutionService.executeProcess(runMessage); + verify(process, times(1)).defineSteps(); + verify(notificationService, times(1)).updateStepsStatuses(eq(executionId), argThat(steps -> + steps.size() == 3 && + steps.get(0).getStatus() == StepStatus.SCHEDULED && + steps.get(0).getId().equals(loadNetworkStep.getId()) && + steps.get(0).getStepType().equals(loadNetworkStep.getType().getName()) && + steps.get(0).getStepOrder() == 0 && + steps.get(1).getStatus() == StepStatus.SCHEDULED && + steps.get(1).getId().equals(applyModificationsStep.getId()) && + steps.get(1).getStepType().equals(applyModificationsStep.getType().getName()) && + steps.get(1).getStepOrder() == 1 && + steps.get(2).getStatus() == StepStatus.SCHEDULED && + steps.get(2).getId().equals(runComputationStep.getId()) && + steps.get(2).getStepType().equals(runComputationStep.getType().getName()) && + steps.get(2).getStepOrder() == 2 + )); + verify(process).execute(argThat(context -> context.getExecutionId().equals(executionId) && context.getCaseUuid().equals(caseUuid) &&