Skip to content

Commit

Permalink
Add interrupt pending feature
Browse files Browse the repository at this point in the history
  • Loading branch information
SCHWITZGUEBEL Marc Ext committed Jul 25, 2024
1 parent b851bc5 commit 3d22478
Show file tree
Hide file tree
Showing 24 changed files with 251 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("cse-cc-runner")
public class UrlWhitelistConfiguration {
public class UrlConfiguration {
private final List<String> whitelist = new ArrayList<>();
private String interruptServerUrl;

public List<String> getWhitelist() {
return whitelist;
}

public String getInterruptServerUrl() {
return interruptServerUrl;
}

public void setInterruptServerUrl(String interruptServerUrl) {
this.interruptServerUrl = interruptServerUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.farao_community.farao.cse.export_runner.app.FileUtil;
import com.farao_community.farao.cse.export_runner.app.configurations.ProcessConfiguration;
import com.farao_community.farao.cse.export_runner.app.configurations.UrlConfiguration;
import com.farao_community.farao.cse.network_processing.CracCreationParametersService;
import com.farao_community.farao.cse.network_processing.busbar_change.BusBarChangePostProcessor;
import com.farao_community.farao.cse.network_processing.busbar_change.BusBarChangePreProcessor;
Expand All @@ -31,6 +32,9 @@
import com.powsybl.openrao.data.raoresultapi.RaoResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.io.InputStream;
Expand Down Expand Up @@ -60,8 +64,10 @@ public class CseExportRunner {
private final Logger businessLogger;
private final ProcessConfiguration processConfiguration;
private final MerchantLineService merchantLineService;
private final RestTemplateBuilder restTemplateBuilder;
private final UrlConfiguration urlConfiguration;

public CseExportRunner(FileImporter fileImporter, FileExporter fileExporter, PiSaService pisaService, RaoRunnerService raoRunnerService, TtcRaoService ttcRaoService, Logger businessLogger, ProcessConfiguration processConfiguration, MerchantLineService merchantLineService) {
public CseExportRunner(FileImporter fileImporter, FileExporter fileExporter, PiSaService pisaService, RaoRunnerService raoRunnerService, TtcRaoService ttcRaoService, Logger businessLogger, ProcessConfiguration processConfiguration, MerchantLineService merchantLineService, RestTemplateBuilder restTemplateBuilder, UrlConfiguration urlConfiguration) {
this.fileImporter = fileImporter;
this.fileExporter = fileExporter;
this.pisaService = pisaService;
Expand All @@ -70,11 +76,19 @@ public CseExportRunner(FileImporter fileImporter, FileExporter fileExporter, PiS
this.businessLogger = businessLogger;
this.processConfiguration = processConfiguration;
this.merchantLineService = merchantLineService;
this.restTemplateBuilder = restTemplateBuilder;
this.urlConfiguration = urlConfiguration;
}

public CseExportResponse run(CseExportRequest cseExportRequest) {
String logsFileUrl = ""; //TODO

if (checkIsInterrupted(cseExportRequest)) {
businessLogger.warn("Computation has been interrupted for timestamp {}", cseExportRequest.getTargetProcessDateTime());
LOGGER.info("Response sent for timestamp {} : run has been interrupted", cseExportRequest.getTargetProcessDateTime());
return new CseExportResponse(cseExportRequest.getId(), ttcRaoService.saveFailedTtcRao(cseExportRequest), "", logsFileUrl, true);
}

// Check on cgm file name
FileUtil.checkCgmFileName(cseExportRequest.getCgmUrl(), cseExportRequest.getProcessType());

Expand Down Expand Up @@ -102,7 +116,7 @@ public CseExportResponse run(CseExportRequest cseExportRequest) {
cseExportRequest.getTargetProcessDateTime());
String artefactDestinationPath = fileExporter.getDestinationPath(cseExportRequest.getTargetProcessDateTime(), cseExportRequest.getProcessType(), GridcapaFileGroup.ARTIFACT);
try {
RaoResponse raoResponse = raoRunnerService.run(cseExportRequest.getId(), initialNetworkUrl, cracInJsonFormatUrl, raoParametersUrl, artefactDestinationPath);
RaoResponse raoResponse = raoRunnerService.run(cseExportRequest.getId(), cseExportRequest.getCurrentRunId(), initialNetworkUrl, cracInJsonFormatUrl, raoParametersUrl, artefactDestinationPath);

Network networkWithPra = fileImporter.importNetwork(raoResponse.getNetworkWithPraFileUrl());
BusBarChangePostProcessor.process(networkWithPra, busBarChangeSwitchesSet);
Expand Down Expand Up @@ -146,4 +160,13 @@ private void runLoadFlow(Network network) {
throw new CseInternalException(String.format("Loadflow computation diverged on network %s", network.getId()));
}
}

private boolean checkIsInterrupted(CseExportRequest cseExportRequest) {
ResponseEntity<Boolean> responseEntity = restTemplateBuilder.build().getForEntity(getInterruptedUrl(cseExportRequest.getCurrentRunId()), Boolean.class);
return responseEntity.getBody() != null && responseEntity.getStatusCode() == HttpStatus.OK && responseEntity.getBody();
}

private String getInterruptedUrl(String runId) {
return urlConfiguration.getInterruptServerUrl() + runId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import com.farao_community.farao.cse.data.CseDataException;
import com.farao_community.farao.cse.export_runner.app.FileUtil;
import com.farao_community.farao.cse.export_runner.app.configurations.UrlWhitelistConfiguration;
import com.farao_community.farao.cse.export_runner.app.configurations.UrlConfiguration;
import com.farao_community.farao.cse.runner.api.exception.CseInvalidDataException;

import com.powsybl.openrao.data.cracapi.Crac;
Expand All @@ -30,11 +30,11 @@
*/
@Service
public class FileImporter {
private final UrlWhitelistConfiguration urlWhitelistConfiguration;
private final UrlConfiguration urlConfiguration;
private final Logger businessLogger;

public FileImporter(UrlWhitelistConfiguration urlWhitelistConfiguration, Logger businessLogger) {
this.urlWhitelistConfiguration = urlWhitelistConfiguration;
public FileImporter(UrlConfiguration urlConfiguration, Logger businessLogger) {
this.urlConfiguration = urlConfiguration;
this.businessLogger = businessLogger;
}

Expand All @@ -54,7 +54,7 @@ public RaoResult importRaoResult(String raoResultUrl, Crac crac) {

private InputStream openUrlStream(String urlString) {
try {
if (urlWhitelistConfiguration.getWhitelist().stream().noneMatch(urlString::startsWith)) {
if (urlConfiguration.getWhitelist().stream().noneMatch(urlString::startsWith)) {
throw new CseInvalidDataException(String.format("URL '%s' is not part of application's whitelisted url's.", urlString));
}
URL url = new URL(urlString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public RaoRunnerService(RaoRunnerClient raoRunnerClient) {
this.raoRunnerClient = raoRunnerClient;
}

public RaoResponse run(String id, String networkPresignedUrl, String cracInJsonFormatUrl, String raoParametersUrl, String artifactDestinationPath) throws CseInternalException, RaoInterruptionException {
RaoRequest raoRequest = buildRaoRequest(id, networkPresignedUrl, cracInJsonFormatUrl, raoParametersUrl, artifactDestinationPath);
public RaoResponse run(String id, String runId, String networkPresignedUrl, String cracInJsonFormatUrl, String raoParametersUrl, String artifactDestinationPath) throws CseInternalException, RaoInterruptionException {
RaoRequest raoRequest = buildRaoRequest(id, runId, networkPresignedUrl, cracInJsonFormatUrl, raoParametersUrl, artifactDestinationPath);
try {
LOGGER.info("RAO request sent: {}", raoRequest);
RaoResponse raoResponse = raoRunnerClient.runRao(raoRequest);
Expand All @@ -45,9 +45,10 @@ public RaoResponse run(String id, String networkPresignedUrl, String cracInJsonF
}
}

private RaoRequest buildRaoRequest(String id, String networkPresignedUrl, String cracUrl, String raoParametersUrl, String artifactDestinationPath) {
private RaoRequest buildRaoRequest(String id, String runId, String networkPresignedUrl, String cracUrl, String raoParametersUrl, String artifactDestinationPath) {
return new RaoRequest.RaoRequestBuilder()
.withId(id)
.withRunId(runId)
.withNetworkFileUrl(networkPresignedUrl)
.withCracFileUrl(cracUrl)
.withRaoParametersFileUrl(raoParametersUrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@
*/
package com.farao_community.farao.cse.export_runner.app.services;

import com.farao_community.farao.cse.runner.api.resource.CseExportRequest;
import com.farao_community.farao.cse.runner.api.resource.CseExportResponse;
import com.farao_community.farao.cse.runner.api.resource.ProcessType;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.time.OffsetDateTime;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* @author Amira Kahya {@literal <amira.kahya at rte-france.com>}
Expand All @@ -24,6 +37,12 @@ class CseExportRunnerTest {
@Autowired
private CseExportRunner cseExportRunner;

@MockBean
private RestTemplateBuilder restTemplateBuilder;

@MockBean
private TtcRaoService ttcRaoService;

@Test
void getFinalNetworkFilenameTest() {
OffsetDateTime processTargetDate = OffsetDateTime.parse("2022-10-20T16:30Z");
Expand All @@ -33,4 +52,25 @@ void getFinalNetworkFilenameTest() {
assertEquals(expectedFilenameWithoutExtension, actualFilenameWithoutExtension);

}

@Test
void runInterruptPendingCase() {
CseExportRequest request = Mockito.mock(CseExportRequest.class);
Mockito.when(request.getId()).thenReturn("ID");
Mockito.when(request.getCurrentRunId()).thenReturn("RUNID");
Mockito.when(request.getProcessType()).thenReturn(ProcessType.D2CC);
Mockito.when(request.getTargetProcessDateTime()).thenReturn(OffsetDateTime.now());
Mockito.when(request.getCgmUrl()).thenReturn("testCgmUrl");

RestTemplate restTemplate = mock(RestTemplate.class);
ResponseEntity<Boolean> responseEntity = mock(ResponseEntity.class);
when(restTemplateBuilder.build()).thenReturn(restTemplate);
when(restTemplate.getForEntity(anyString(), eq(Boolean.class))).thenReturn(responseEntity);
when(responseEntity.getStatusCode()).thenReturn(HttpStatus.OK);
when(responseEntity.getBody()).thenReturn(true);

CseExportResponse cseExportResponse = cseExportRunner.run(request);
assertTrue(cseExportResponse.isInterrupted());
assertEquals("ID", cseExportResponse.getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class RaoRunnerServiceTest {
private RaoRunnerService raoRunnerService;

private final String id = "testId";
private final String runId = "testRunId";
private final String networkPresignedUrl = "http://network.url";
private final String cracInJsonFormatUrl = "http://crac.url";
private final String raoParametersUrl = "http://parameters.url";
Expand All @@ -44,7 +45,7 @@ void testRunSuccessful() throws CseInternalException, RaoInterruptionException {

when(raoRunnerClient.runRao(any(RaoRequest.class))).thenReturn(expectedResponse);

RaoResponse actualResponse = raoRunnerService.run(id, networkPresignedUrl, cracInJsonFormatUrl, raoParametersUrl, artifactDestinationPath);
RaoResponse actualResponse = raoRunnerService.run(id, runId, networkPresignedUrl, cracInJsonFormatUrl, raoParametersUrl, artifactDestinationPath);

assertEquals(expectedResponse, actualResponse);
}
Expand All @@ -54,7 +55,7 @@ void testRunThrowsCseInternalException() {
when(raoRunnerClient.runRao(any())).thenThrow(new RuntimeException("Test exception"));

Exception exception = assertThrows(CseInternalException.class, () -> {
raoRunnerService.run(id, networkPresignedUrl, cracInJsonFormatUrl, raoParametersUrl, artifactDestinationPath);
raoRunnerService.run(id, runId, networkPresignedUrl, cracInJsonFormatUrl, raoParametersUrl, artifactDestinationPath);
});

String expectedMessage = "RAO run failed";
Expand All @@ -67,13 +68,15 @@ void testRunThrowsCseInternalException() {
void testRaoRequestValues() {
RaoRequest raoRequest = new RaoRequest.RaoRequestBuilder()
.withId(id)
.withRunId(runId)
.withNetworkFileUrl(networkPresignedUrl)
.withCracFileUrl(cracInJsonFormatUrl)
.withRaoParametersFileUrl(raoParametersUrl)
.withResultsDestination(artifactDestinationPath)
.build();

assertEquals("testId", raoRequest.getId());
assertEquals("testRunId", raoRequest.getRunId());
assertEquals("http://network.url", raoRequest.getNetworkFileUrl());
assertEquals("http://crac.url", raoRequest.getCracFileUrl());
assertEquals("http://parameters.url", raoRequest.getRaoParametersFileUrl());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class RequestServiceTest {

@Test
void testSuccessRequestService() {
CseExportRequest cseRequest = new CseExportRequest(UUID.randomUUID().toString(), null, null, "", "");
CseExportRequest cseRequest = new CseExportRequest(UUID.randomUUID().toString(), UUID.randomUUID().toString(), null, null, "", "");
CseExportResponse cseResponse = new CseExportResponse(cseRequest.getId(), "", "", "", false);
byte[] req = jsonApiConverter.toJsonMessage(cseRequest, CseExportRequest.class);
byte[] resp = jsonApiConverter.toJsonMessage(cseResponse, CseExportResponse.class);
Expand All @@ -63,7 +63,7 @@ void testSuccessRequestService() {

@Test
void testInterruptedRequestService() {
CseExportRequest cseRequest = new CseExportRequest(UUID.randomUUID().toString(), null, null, "", "");
CseExportRequest cseRequest = new CseExportRequest(UUID.randomUUID().toString(), UUID.randomUUID().toString(), null, null, "", "");
CseExportResponse cseResponse = new CseExportResponse(cseRequest.getId(), "", "", "", true);
byte[] request = jsonApiConverter.toJsonMessage(cseRequest, CseExportRequest.class);
byte[] expectedResponse = jsonApiConverter.toJsonMessage(cseResponse, CseExportResponse.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ cse-cc-runner:
whitelist:
- http://minio:9000/
- http://localhost:9000/
interrupt-server-url: http://testUrl/interrupted/
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("cse-cc-runner")
public class UrlWhitelistConfiguration {
public class UrlConfiguration {
private final List<String> whitelist = new ArrayList<>();
private String interruptServerUrl;

public List<String> getWhitelist() {
return whitelist;
}

public String getInterruptServerUrl() {
return interruptServerUrl;
}

public void setInterruptServerUrl(String interruptServerUrl) {
this.interruptServerUrl = interruptServerUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ public DichotomyResult<DichotomyRaoResponse> runDichotomy(CseRequest cseRequest,
private NetworkValidator<DichotomyRaoResponse> getNetworkValidator(CseRequest request, CseData cseData, Set<String> forcedPrasIds) {
final boolean isImportEcProcess = request.isImportEcProcess();
return new RaoRunnerValidator(
request.getProcessType(),
request.getId(),
request.getTargetProcessDateTime(),
request,
cseData.getJsonCracUrl(),
fileExporter.saveRaoParameters(request.getTargetProcessDateTime(), request.getProcessType(), isImportEcProcess),
raoRunnerClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.farao_community.farao.cse.import_runner.app.services.ForcedPrasHandler;
import com.farao_community.farao.cse.import_runner.app.util.FlowEvaluator;
import com.farao_community.farao.cse.import_runner.app.util.MinioStorageHelper;
import com.farao_community.farao.cse.runner.api.resource.CseRequest;
import com.farao_community.farao.cse.runner.api.resource.ProcessType;
import com.farao_community.farao.dichotomy.api.exceptions.RaoInterruptionException;
import com.powsybl.openrao.commons.Unit;
Expand Down Expand Up @@ -43,6 +44,7 @@ public class RaoRunnerValidator implements NetworkValidator<DichotomyRaoResponse

private final ProcessType processType;
private final String requestId;
private final String currentRunId;
private final OffsetDateTime processTargetDateTime;
private final String cracUrl;
private final String raoParametersUrl;
Expand All @@ -54,9 +56,7 @@ public class RaoRunnerValidator implements NetworkValidator<DichotomyRaoResponse
private final boolean isImportEcProcess;
private int variantCounter = 0;

public RaoRunnerValidator(ProcessType processType,
String requestId,
OffsetDateTime processTargetDateTime,
public RaoRunnerValidator(CseRequest cseRequest,
String cracUrl,
String raoParametersUrl,
RaoRunnerClient raoRunnerClient,
Expand All @@ -65,9 +65,10 @@ public RaoRunnerValidator(ProcessType processType,
ForcedPrasHandler forcedPrasHandler,
Set<String> forcedPrasIds,
boolean isImportEcProcess) {
this.processType = processType;
this.requestId = requestId;
this.processTargetDateTime = processTargetDateTime;
this.processType = cseRequest.getProcessType();
this.requestId = cseRequest.getId();
this.currentRunId = cseRequest.getCurrentRunId();
this.processTargetDateTime = cseRequest.getTargetProcessDateTime();
this.cracUrl = cracUrl;
this.raoParametersUrl = raoParametersUrl;
this.raoRunnerClient = raoRunnerClient;
Expand Down Expand Up @@ -130,6 +131,7 @@ private Set<String> applyForcedPras(Crac crac, Network network) {
public RaoRequest buildRaoRequest(String networkPreSignedUrl, String baseDirPathForCurrentStep, List<String> appliedRemedialActionInPreviousStep) {
RaoRequest.RaoRequestBuilder builder = new RaoRequest.RaoRequestBuilder()
.withId(requestId)
.withRunId(currentRunId)
.withNetworkFileUrl(networkPreSignedUrl)
.withCracFileUrl(cracUrl)
.withResultsDestination(baseDirPathForCurrentStep);
Expand Down
Loading

0 comments on commit 3d22478

Please sign in to comment.