-
Notifications
You must be signed in to change notification settings - Fork 1
POC : use existing servers to run cyclic chain #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b0866ac
24999ae
4bd069d
f52b58e
1221e18
80a7c1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /** | ||
| * 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.commons; | ||
|
|
||
| import lombok.Getter; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| /** | ||
| * @author Franck Lecuyer <franck.lecuyer at rte-france.com> | ||
| */ | ||
| @Getter | ||
| public class CaseResultInfos { | ||
| private final UUID caseResultUuid; | ||
|
|
||
| private final UUID executionUuid; | ||
|
|
||
| private final UUID reportUuid; | ||
|
|
||
| private final UUID resultUuid; | ||
|
|
||
| private final String stepType; | ||
|
|
||
| private final String status; | ||
|
|
||
| public CaseResultInfos(UUID caseResultUuid, UUID executionUuid, UUID reportUuid, UUID resultUuid, String stepType, String status) { | ||
| this.caseResultUuid = caseResultUuid; | ||
| this.executionUuid = executionUuid; | ||
| this.reportUuid = reportUuid; | ||
| this.resultUuid = resultUuid; | ||
| this.stepType = stepType; | ||
| this.status = status; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,168 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 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.services; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.CaseResultInfos; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.messaging.ProcessExecutionStep; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.messaging.ProcessRunMessage; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.processconfig.ProcessConfig; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.processconfig.SecurityAnalysisConfig; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.processexecution.ProcessStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.processexecution.StepStatus; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.commons.types.result.ResultType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.gridsuite.monitor.server.services.processexecution.ProcessExecutionService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.slf4j.Logger; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.slf4j.LoggerFactory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.context.annotation.Bean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.context.annotation.Configuration; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.messaging.Message; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.Instant; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Map; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.UUID; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.concurrent.ConcurrentHashMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.function.Consumer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @author Franck Lecuyer <franck.lecuyer at rte-france.com> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class ConsumerServiceUsingServers { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerServiceUsingServers.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final NetworkModificationRestService networkModificationRestService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final SecurityAnalysisRestService securityAnalysisRestService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ProcessExecutionService processExecutionService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private record ProcessExecutionContext( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID applyModificationsStepId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID securityAnalysisStepId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID caseUuid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID securityAnalysisParametersUuid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID loadflowParametersUuid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) { } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final Map<UUID, ProcessExecutionContext> processExecutionContexts = new ConcurrentHashMap<>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Autowired | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ConsumerServiceUsingServers(NetworkModificationRestService networkModificationRestService, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SecurityAnalysisRestService securityAnalysisRestService, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProcessExecutionService processExecutionService) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.networkModificationRestService = networkModificationRestService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.securityAnalysisRestService = securityAnalysisRestService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.processExecutionService = processExecutionService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Bean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public <T extends ProcessConfig> Consumer<Message<ProcessRunMessage<T>>> consumeRunUsingServers() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // consume message to launch process | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return message -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProcessRunMessage<T> processRunMessage = message.getPayload(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID caseUuid = processRunMessage.caseUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID executionId = processRunMessage.executionId(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProcessConfig processConfig = processRunMessage.config(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<UUID> modificationUuids = processConfig.modificationUuids(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID applyModificationsStepId = UUID.randomUUID(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID securityAnalysisStepId = UUID.randomUUID(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID securityAnalysisParametersUuid = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID loadflowParametersUuid = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch (processConfig.processType()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Check warning on line 79 in monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerServiceUsingServers.java
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case SECURITY_ANALYSIS -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| securityAnalysisParametersUuid = ((SecurityAnalysisConfig) processConfig).securityAnalysisParametersUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loadflowParametersUuid = ((SecurityAnalysisConfig) processConfig).loadflowParametersUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionContexts.put(executionId, new ProcessExecutionContext( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| applyModificationsStepId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| securityAnalysisStepId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| caseUuid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| securityAnalysisParametersUuid, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loadflowParametersUuid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateExecutionStatus(executionId, ProcessStatus.RUNNING, null, Instant.now(), null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateStepStatus(executionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new ProcessExecutionStep(applyModificationsStepId, "APPLY_MODIFICATIONS", 0, StepStatus.RUNNING, null, null, null, Instant.now(), null, null)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateStepStatus(executionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new ProcessExecutionStep(securityAnalysisStepId, "SECURITY_ANALYSIS", 1, StepStatus.SCHEDULED, null, null, null, null, null, null)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // call network-modification-server to apply modifications | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| networkModificationRestService.applyModifications(caseUuid, executionId, modificationUuids); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+100
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle REST client failures to avoid stuck RUNNING executions. Lines 99-100 and 132 call external services without exception handling. If either call throws, execution state can remain inconsistent and context may leak. 🧯 Proposed fix- networkModificationRestService.applyModifications(caseUuid, executionId, modificationUuids);
+ try {
+ networkModificationRestService.applyModifications(caseUuid, executionId, modificationUuids);
+ } catch (RuntimeException ex) {
+ LOGGER.error("applyModifications failed for executionId: {}", executionId, ex);
+ monitorService.updateExecutionStatus(executionId, ProcessStatus.FAILED, null, null, Instant.now());
+ processExecutionContexts.remove(executionId);
+ }
...
if (stepStatus == StepStatus.COMPLETED) {
// call security-analysis-server to run security analysis
- securityAnalysisRestService.runSecurityAnalysis(caseResultUuid, executionId, processExecutionContext.contingencies(), processExecutionContext.parametersUuid());
+ try {
+ securityAnalysisRestService.runSecurityAnalysis(caseResultUuid, executionId, processExecutionContext.contingencies(), processExecutionContext.parametersUuid());
+ } catch (RuntimeException ex) {
+ LOGGER.error("runSecurityAnalysis failed for executionId: {}", executionId, ex);
+ monitorService.updateExecutionStatus(executionId, ProcessStatus.FAILED, null, null, Instant.now());
+ processExecutionContexts.remove(executionId);
+ }
} else {
processExecutionContexts.remove(executionId);
}Also applies to: 130-133 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+86
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard against duplicate run messages to avoid double modifications. Message delivery is typically at-least-once; this code generates new step IDs and calls 🛡️ Proposed deduplication guard- processExecutionContexts.put(executionId, new ProcessExecutionContext(
- applyModificationsStepId,
- securityAnalysisStepId,
- caseUuid,
- contingencies,
- parametersUuid
- ));
+ ProcessExecutionContext newContext = new ProcessExecutionContext(
+ applyModificationsStepId,
+ securityAnalysisStepId,
+ caseUuid,
+ contingencies,
+ parametersUuid
+ );
+ ProcessExecutionContext existing = processExecutionContexts.putIfAbsent(executionId, newContext);
+ if (existing != null) {
+ LOGGER.warn("Duplicate run message ignored for executionId: {}", executionId);
+ return;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Bean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Consumer<Message<CaseResultInfos>> consumeNetworkModifications() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // consume message received from network-modification-server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return message -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CaseResultInfos caseResultInfos = message.getPayload(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID caseResultUuid = caseResultInfos.getCaseResultUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID executionId = caseResultInfos.getExecutionUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String stepType = caseResultInfos.getStepType(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID reportUuid = caseResultInfos.getReportUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StepStatus stepStatus = StepStatus.valueOf(caseResultInfos.getStatus()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProcessExecutionContext processExecutionContext = processExecutionContexts.get(executionId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (processExecutionContext == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOGGER.error("Process execution context not found for executionId: {}", executionId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateStepStatus(executionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new ProcessExecutionStep(processExecutionContext.applyModificationsStepId(), stepType, 0, stepStatus, null, null, reportUuid, null, Instant.now(), caseResultUuid)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateStepStatus(executionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new ProcessExecutionStep(processExecutionContext.securityAnalysisStepId(), "SECURITY_ANALYSIS", 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stepStatus == StepStatus.COMPLETED ? StepStatus.RUNNING : StepStatus.SKIPPED, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| null, null, null, Instant.now(), null, null)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (stepStatus == StepStatus.COMPLETED) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // call security-analysis-server to run security analysis | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| securityAnalysisRestService.runSecurityAnalysis(caseResultUuid, executionId, processExecutionContext.securityAnalysisParametersUuid(), processExecutionContext.loadflowParametersUuid); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionContexts.remove(executionId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+131
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update execution status when network modifications fail. On non- 🧭 Propagate failure to the execution status if (stepStatus == StepStatus.COMPLETED) {
// call security-analysis-server to run security analysis
securityAnalysisRestService.runSecurityAnalysis(caseResultUuid, executionId, processExecutionContext.contingencies(), processExecutionContext.parametersUuid());
} else {
+ monitorService.updateExecutionStatus(executionId, ProcessStatus.FAILED, null, null, Instant.now());
processExecutionContexts.remove(executionId);
}🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Bean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Consumer<Message<CaseResultInfos>> consumeSecurityAnalysis() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // consume message received from security-analysis-server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return message -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CaseResultInfos caseResultInfos = message.getPayload(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID executionId = caseResultInfos.getExecutionUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String stepType = caseResultInfos.getStepType(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID reportUuid = caseResultInfos.getReportUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID resultUuid = caseResultInfos.getResultUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StepStatus stepStatus = StepStatus.valueOf(caseResultInfos.getStatus()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UUID caseResultUuid = caseResultInfos.getCaseResultUuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+150
to
+152
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, locate the file and examine the current state around lines 148-149
find . -type f -name "ConsumerServiceUsingServers.java" -exec wc -l {} \;Repository: gridsuite/monitor-core Length of output: 171 🏁 Script executed: # Check the file structure and content around the specified lines
find . -type f -name "ConsumerServiceUsingServers.java" -exec sed -n '140,160p' {} +Repository: gridsuite/monitor-core Length of output: 1332 🏁 Script executed: # Find CaseResultInfos class definition
fd 'CaseResultInfos.java' -x cat -n {}Repository: gridsuite/monitor-core Length of output: 1386 🏁 Script executed: # Search for all StepStatus.valueOf usages in the codebase
rg -n "StepStatus\.valueOf" -g '*.java' -B2 -A2Repository: gridsuite/monitor-core Length of output: 1740 🏁 Script executed: # Find consumeNetworkModifications method
rg -n "consumeNetworkModifications" -g '*.java' -B2 -A10Repository: gridsuite/monitor-core Length of output: 2030 🏁 Script executed: # Check StepStatus enum definition to see valid values
fd 'StepStatus.java' -x cat -n {}Repository: gridsuite/monitor-core Length of output: 663 🏁 Script executed: # Check the method name for line 148
sed -n '130,150p' ./monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerServiceUsingServers.javaRepository: gridsuite/monitor-core Length of output: 1133 🏁 Script executed: # Search for any other StepStatus usages or related parsing
rg -n "StepStatus|getStatus" ./monitor-server/src/main/java/org/gridsuite/monitor/server/services/ConsumerServiceUsingServers.java -B1 -A1Repository: gridsuite/monitor-core Length of output: 2294 🏁 Script executed: # Check if there's any validation or documentation about status values from external servers
rg -n "status|Status" ./monitor-server/src/main/java/org/gridsuite/monitor/commons/CaseResultInfos.java -B2 -A2Repository: gridsuite/monitor-core Length of output: 187 Harden status parsing from external servers in two locations.
Use safe parsing with error handling and fallback in both methods. 🛡️ Safer status parsing pattern- StepStatus stepStatus = StepStatus.valueOf(caseResultInfos.getStatus());
+ StepStatus stepStatus;
+ try {
+ stepStatus = StepStatus.valueOf(caseResultInfos.getStatus());
+ } catch (IllegalArgumentException ex) {
+ LOGGER.error("Unsupported step status '{}' for executionId: {}", caseResultInfos.getStatus(), executionId, ex);
+ monitorService.updateExecutionStatus(executionId, ProcessStatus.FAILED, null, null, Instant.now());
+ processExecutionContexts.remove(executionId);
+ return;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProcessExecutionContext processExecutionContext = processExecutionContexts.get(executionId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (processExecutionContext == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOGGER.error("Process execution context not found for executionId: {}", executionId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateStepStatus(executionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new ProcessExecutionStep(processExecutionContext.securityAnalysisStepId(), stepType, 1, stepStatus, resultUuid, ResultType.SECURITY_ANALYSIS, reportUuid, null, Instant.now(), caseResultUuid)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionService.updateExecutionStatus(executionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stepStatus == StepStatus.COMPLETED ? ProcessStatus.COMPLETED : ProcessStatus.FAILED, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| null, null, Instant.now()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processExecutionContexts.remove(executionId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| /** | ||
| * 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.services; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.boot.web.client.RestTemplateBuilder; | ||
| import org.springframework.http.HttpEntity; | ||
| import org.springframework.http.HttpHeaders; | ||
| import org.springframework.http.HttpMethod; | ||
| import org.springframework.http.MediaType; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.web.client.RestTemplate; | ||
| import org.springframework.web.util.UriComponentsBuilder; | ||
|
|
||
| import java.util.List; | ||
| import java.util.UUID; | ||
|
|
||
| /** | ||
| * @author Franck Lecuyer <franck.lecuyer at rte-france.com> | ||
| */ | ||
| @Service | ||
| public class NetworkModificationRestService { | ||
| private static final String NETWORK_MODIFICATION_SERVER_API_VERSION = "v1"; | ||
| private static final String DELIMITER = "/"; | ||
|
|
||
| private final RestTemplate networkModificationServerRest; | ||
| private final String networkModificationServerBaseUri; | ||
|
|
||
| public NetworkModificationRestService(@Value("${gridsuite.services.network-modification-server.base-uri:http://network-modification-server/}") String networkModificationServerBaseUri, | ||
| RestTemplateBuilder restTemplateBuilder) { | ||
| this.networkModificationServerRest = restTemplateBuilder.build(); | ||
| this.networkModificationServerBaseUri = networkModificationServerBaseUri; | ||
| } | ||
|
|
||
| public void applyModifications(UUID caseUuid, UUID executionId, List<UUID> modificationUuids) { | ||
| var uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + NETWORK_MODIFICATION_SERVER_API_VERSION + DELIMITER + "cases/{caseUuid}/network-composite-modifications"); | ||
| var path = uriComponentsBuilder | ||
| .queryParam("executionUuid", executionId) | ||
| .queryParam("uuids", modificationUuids) | ||
| .buildAndExpand(caseUuid) | ||
| .toUriString(); | ||
|
|
||
| HttpHeaders headers = new HttpHeaders(); | ||
| headers.setContentType(MediaType.APPLICATION_JSON); | ||
| HttpEntity httpEntity = new HttpEntity<>(null, headers); | ||
|
Check warning on line 50 in monitor-server/src/main/java/org/gridsuite/monitor/server/services/NetworkModificationRestService.java
|
||
|
|
||
| networkModificationServerRest.exchange(networkModificationServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| /** | ||
| * 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.services; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.boot.web.client.RestTemplateBuilder; | ||
| import org.springframework.http.HttpEntity; | ||
| import org.springframework.http.HttpHeaders; | ||
| import org.springframework.http.HttpMethod; | ||
| import org.springframework.http.MediaType; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.web.client.RestTemplate; | ||
| import org.springframework.web.util.UriComponentsBuilder; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| /** | ||
| * @author Franck Lecuyer <franck.lecuyer at rte-france.com> | ||
| */ | ||
| @Service | ||
| public class SecurityAnalysisRestService { | ||
| private static final String SECURITY_ANALYSIS_SERVER_API_VERSION = "v1"; | ||
| private static final String DELIMITER = "/"; | ||
|
|
||
| private final RestTemplate securityAnalysisServerRest; | ||
| private final String securityAnalysisServerBaseUri; | ||
|
|
||
| public SecurityAnalysisRestService(@Value("${gridsuite.services.security-analysis-server.base-uri:http://security-analysis-server/}") String securityAnalysisServerBaseUri, | ||
| RestTemplateBuilder restTemplateBuilder) { | ||
| this.securityAnalysisServerRest = restTemplateBuilder.build(); | ||
| this.securityAnalysisServerBaseUri = securityAnalysisServerBaseUri; | ||
| } | ||
|
|
||
| public void runSecurityAnalysis(UUID caseUuid, UUID executionId, UUID securityAnalysisParametersUuid, UUID loadflowParametersUuid) { | ||
| var uriComponentsBuilder = UriComponentsBuilder.fromPath(DELIMITER + SECURITY_ANALYSIS_SERVER_API_VERSION + DELIMITER + "/cases/{caseUuid}/run-and-save"); | ||
| var path = uriComponentsBuilder | ||
| .queryParam("executionUuid", executionId) | ||
| .queryParam("parametersUuid", securityAnalysisParametersUuid) | ||
| .queryParam("loadFlowParametersUuid", loadflowParametersUuid) | ||
| .buildAndExpand(caseUuid) | ||
| .toUriString(); | ||
|
|
||
| HttpHeaders headers = new HttpHeaders(); | ||
| headers.setContentType(MediaType.APPLICATION_JSON); | ||
| HttpEntity httpEntity = new HttpEntity<>(null, headers); | ||
|
Check warning on line 50 in monitor-server/src/main/java/org/gridsuite/monitor/server/services/SecurityAnalysisRestService.java
|
||
|
|
||
| securityAnalysisServerRest.exchange(securityAnalysisServerBaseUri + path, HttpMethod.POST, httpEntity, Void.class); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: gridsuite/monitor-core
Length of output: 2037
🏁 Script executed:
Repository: gridsuite/monitor-core
Length of output: 244
🏁 Script executed:
Repository: gridsuite/monitor-core
Length of output: 160
🏁 Script executed:
Repository: gridsuite/monitor-core
Length of output: 1817
🏁 Script executed:
Repository: gridsuite/monitor-core
Length of output: 680
🏁 Script executed:
Repository: gridsuite/monitor-core
Length of output: 2266
Fix parameter order mismatch in MonitorService call to the 5-parameter overload.
The call at
MonitorService.java:264passes arguments in the wrong positions for the two adjacentStringparameters:But the method signature expects:
This swaps the parameters:
nullis passed tobindingName(causingpublisher.send(null, ...)) andbindingNameis passed todebugFileLocation. Correct the argument order:Fix parameter order
Alternatively, to avoid this fragility in the future, consider whether this call should use the 4-parameter overload instead and let the routing logic remain centralized in
NotificationService.🤖 Prompt for AI Agents