Skip to content

Debug computation mode (migration with ws-commons) #19

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

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
31 changes: 30 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
<jib.from.image>powsybl/java-dynawo:3.0.0</jib.from.image>
<liquibase-hibernate-package>org.gridsuite.dynamicsecurityanalysis.server</liquibase-hibernate-package>
<sonar.organization>gridsuite</sonar.organization>
<spring-cloud-aws.version>3.2.0</spring-cloud-aws.version>
<sonar.projectKey>org.gridsuite:dynamic-security-analysis-server</sonar.projectKey>
<!-- FIXME: powsybl-ws-commons modules'version is overloaded in the dependencies section to be removed at next powsybl-ws-dependencies.version upgrade -->
<powsybl-ws-commons.version>1.26.0-SNAPSHOT</powsybl-ws-commons.version>
</properties>

<build>
Expand Down Expand Up @@ -86,7 +89,26 @@
<dependencyManagement>
<dependencies>
<!-- overrides of imports -->

<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-computation-local</artifactId>
<version>6.8.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-computation</artifactId>
<version>6.8.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-iidm-api</artifactId>
<version>6.8.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-dynamic-security-analysis</artifactId>
<version>6.8.0-SNAPSHOT</version>
</dependency>
<!-- imports -->
<dependency>
<groupId>org.gridsuite</groupId>
Expand Down Expand Up @@ -114,6 +136,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-starter-s3</artifactId>
<version>${spring-cloud-aws.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
Expand All @@ -130,6 +157,7 @@
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-ws-commons</artifactId>
<version>${powsybl-ws-commons.version}</version>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
Expand All @@ -138,6 +166,7 @@
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-dynawo-security-analysis</artifactId>
<version>2.9.0-SNAPSHOT</version>
</dependency>

<!-- runtime dependencies -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.gridsuite.dynamicsecurityanalysis.server.service.DynamicSecurityAnalysisService;
import org.gridsuite.dynamicsecurityanalysis.server.service.ParametersService;
import org.gridsuite.dynamicsecurityanalysis.server.service.contexts.DynamicSecurityAnalysisRunContext;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand Down Expand Up @@ -61,6 +62,7 @@ public ResponseEntity<UUID> run(@PathVariable("networkUuid") UUID networkUuid,
@RequestParam(name = REPORTER_ID_HEADER, required = false) String reportName,
@RequestParam(name = REPORT_TYPE_HEADER, required = false, defaultValue = "DynamicSecurityAnalysis") String reportType,
@RequestParam(name = HEADER_PROVIDER, required = false) String provider,
@RequestParam(name = "debug", required = false, defaultValue = "false") boolean debug,
@RequestParam(name = "dynamicSimulationResultUuid") UUID dynamicSimulationResultUuid,
@RequestParam(name = "parametersUuid") UUID parametersUuid,
@RequestHeader(HEADER_USER_ID) String userId) {
Expand All @@ -73,7 +75,8 @@ public ResponseEntity<UUID> run(@PathVariable("networkUuid") UUID networkUuid,
ReportInfos.builder().reportUuid(reportId).reporterId(reportName).computationType(reportType).build(),
userId,
dynamicSimulationResultUuid,
parametersUuid);
parametersUuid,
debug);

UUID resultUuid = dynamicSecurityAnalysisService.runAndSaveResult(dynamicSecurityAnalysisRunContext);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(resultUuid);
Expand Down Expand Up @@ -138,4 +141,13 @@ public ResponseEntity<List<String>> getProviders() {
public ResponseEntity<String> getDefaultProvider() {
return ResponseEntity.ok().body(dynamicSecurityAnalysisService.getDefaultProvider());
}

@GetMapping(value = "/results/{resultUuid}/download-debug-file", produces = "application/json")
@Operation(summary = "Download a dynamic security analysis debug file")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Dynamic security analysis debug file"),
@ApiResponse(responseCode = "404", description = "Dynamic security analysis debug file has not been found")})
public ResponseEntity<Resource> downloadDebugFile(@Parameter(description = "Result UUID") @PathVariable("resultUuid") UUID resultUuid) {
return dynamicSecurityAnalysisService.downloadDebugFile(resultUuid);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package org.gridsuite.dynamicsecurityanalysis.server.entities;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand All @@ -22,14 +23,10 @@
@Setter
@Table(name = "dynamic_security_analysis_result")
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class DynamicSecurityAnalysisResultEntity {

public DynamicSecurityAnalysisResultEntity(UUID id, DynamicSecurityAnalysisStatus status) {
this.id = id;
this.status = status;
}

@Id
@Column(name = "result_uuid")
private UUID id;
Expand All @@ -38,4 +35,7 @@ public DynamicSecurityAnalysisResultEntity(UUID id, DynamicSecurityAnalysisStatu
@Enumerated(EnumType.STRING)
private DynamicSecurityAnalysisStatus status;

@Column(name = "debugFileLocation")
private String debugFileLocation;

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

import org.gridsuite.dynamicsecurityanalysis.server.entities.DynamicSecurityAnalysisResultEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.UUID;
Expand All @@ -18,4 +21,8 @@
*/
@Repository
public interface DynamicSecurityAnalysisResultRepository extends JpaRepository<DynamicSecurityAnalysisResultEntity, UUID> {
@Modifying
@Query("UPDATE DynamicSecurityAnalysisResultEntity r SET r.debugFileLocation = :debugFileLocation WHERE r.id = :resultUuid")
int updateDebugFileLocation(@Param("resultUuid") UUID resultUuid, @Param("debugFileLocation") String debugFileLocation);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
package org.gridsuite.dynamicsecurityanalysis.server.service;

import com.powsybl.ws.commons.computation.service.AbstractComputationResultService;
import jakarta.transaction.Transactional;
import org.gridsuite.dynamicsecurityanalysis.server.DynamicSecurityAnalysisException;
import org.gridsuite.dynamicsecurityanalysis.server.dto.DynamicSecurityAnalysisStatus;
import org.gridsuite.dynamicsecurityanalysis.server.entities.DynamicSecurityAnalysisResultEntity;
import org.gridsuite.dynamicsecurityanalysis.server.repositories.DynamicSecurityAnalysisResultRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -43,7 +43,7 @@ public DynamicSecurityAnalysisResultService(DynamicSecurityAnalysisResultReposit
public void insertStatus(List<UUID> resultUuids, DynamicSecurityAnalysisStatus status) {
Objects.requireNonNull(resultUuids);
resultRepository.saveAll(resultUuids.stream()
.map(uuid -> new DynamicSecurityAnalysisResultEntity(uuid, status)).toList());
.map(uuid -> new DynamicSecurityAnalysisResultEntity(uuid, status, null)).toList());
}

@Transactional
Expand All @@ -65,6 +65,16 @@ public void updateResult(UUID resultUuid, DynamicSecurityAnalysisStatus status)
}

@Override
@Transactional
public void saveDebugFileLocation(UUID resultUuid, String debugFilePath) {
resultRepository.findById(resultUuid).ifPresentOrElse(
(var resultEntity) -> resultRepository.updateDebugFileLocation(resultUuid, debugFilePath),
() -> resultRepository.save(new DynamicSecurityAnalysisResultEntity(resultUuid, DynamicSecurityAnalysisStatus.NOT_DONE, debugFilePath))
);
}

@Override
@Transactional
public void delete(UUID resultUuid) {
Objects.requireNonNull(resultUuid);
resultRepository.deleteById(resultUuid);
Expand All @@ -77,10 +87,20 @@ public void deleteAll() {
}

@Override
@Transactional(readOnly = true)
public DynamicSecurityAnalysisStatus findStatus(UUID resultUuid) {
Objects.requireNonNull(resultUuid);
return resultRepository.findById(resultUuid)
.map(DynamicSecurityAnalysisResultEntity::getStatus)
.orElse(null);
}

@Override
@Transactional(readOnly = true)
public String findDebugFileLocation(UUID resultUuid) {
Objects.requireNonNull(resultUuid);
return resultRepository.findById(resultUuid)
.map(DynamicSecurityAnalysisResultEntity::getDebugFileLocation)
.orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.powsybl.ws.commons.computation.service.AbstractComputationService;
import com.powsybl.ws.commons.computation.service.NotificationService;
import com.powsybl.ws.commons.computation.service.UuidGeneratorService;
import com.powsybl.ws.commons.s3.S3Service;
import org.gridsuite.dynamicsecurityanalysis.server.dto.DynamicSecurityAnalysisStatus;
import org.gridsuite.dynamicsecurityanalysis.server.service.contexts.DynamicSecurityAnalysisResultContext;
import org.gridsuite.dynamicsecurityanalysis.server.service.contexts.DynamicSecurityAnalysisRunContext;
Expand All @@ -36,8 +37,9 @@ public DynamicSecurityAnalysisService(
ObjectMapper objectMapper,
UuidGeneratorService uuidGeneratorService,
DynamicSecurityAnalysisResultService dynamicSecurityAnalysisResultService,
S3Service s3Service,
@Value("${dynamic-security-analysis.default-provider}") String defaultProvider) {
super(notificationService, dynamicSecurityAnalysisResultService, objectMapper, uuidGeneratorService, defaultProvider);
super(notificationService, dynamicSecurityAnalysisResultService, s3Service, objectMapper, uuidGeneratorService, defaultProvider);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.powsybl.security.dynamic.DynamicSecurityAnalysisRunParameters;
import com.powsybl.security.results.PostContingencyResult;
import com.powsybl.ws.commons.computation.service.*;
import com.powsybl.ws.commons.s3.S3Service;
import org.apache.commons.collections4.CollectionUtils;
import org.gridsuite.dynamicsecurityanalysis.server.DynamicSecurityAnalysisException;
import org.gridsuite.dynamicsecurityanalysis.server.dto.DynamicSecurityAnalysisStatus;
Expand Down Expand Up @@ -60,7 +61,7 @@
import static org.gridsuite.dynamicsecurityanalysis.server.DynamicSecurityAnalysisException.Type.CONTINGENCIES_NOT_FOUND;
import static org.gridsuite.dynamicsecurityanalysis.server.DynamicSecurityAnalysisException.Type.DUMP_FILE_ERROR;
import static org.gridsuite.dynamicsecurityanalysis.server.service.DynamicSecurityAnalysisService.COMPUTATION_TYPE;
import static org.gridsuite.dynamicsecurityanalysis.server.utils.Utils.*;
import static org.gridsuite.dynamicsecurityanalysis.server.utils.Utils.getReportNode;

/**
* @author Thang PHAM <quyet-thang.pham at rte-france.com>
Expand All @@ -82,10 +83,11 @@ public DynamicSecurityAnalysisWorkerService(NetworkStoreService networkStoreServ
DynamicSecurityAnalysisObserver observer,
ObjectMapper objectMapper,
DynamicSecurityAnalysisResultService dynamicSecurityAnalysisResultService,
S3Service s3Service,
DynamicSimulationClient dynamicSimulationClient,
ActionsClient actionsClient,
ParametersService parametersService) {
super(networkStoreService, notificationService, reportService, dynamicSecurityAnalysisResultService, executionService, observer, objectMapper);
super(networkStoreService, notificationService, reportService, dynamicSecurityAnalysisResultService, s3Service, executionService, observer, objectMapper);
this.dynamicSimulationClient = Objects.requireNonNull(dynamicSimulationClient);
this.actionsClient = Objects.requireNonNull(actionsClient);
this.parametersService = Objects.requireNonNull(parametersService);
Expand Down Expand Up @@ -167,6 +169,9 @@ public void preRun(DynamicSecurityAnalysisRunContext runContext) {

// create a new dynamic security analysis parameters
DynamicSecurityAnalysisParameters parameters = new DynamicSecurityAnalysisParameters();
if (runContext.getDebugDir() != null) {
parameters.setDebugDir(runContext.getDebugDir().toString());
}
parameters.setDynamicSimulationParameters(dynamicSimulationParameters);

// set start and stop times
Expand Down Expand Up @@ -251,33 +256,36 @@ protected void clean(AbstractResultContext<DynamicSecurityAnalysisRunContext> re
super.clean(resultContext);
// clean working directory
Path workDir = resultContext.getRunContext().getWorkDir();
removeWorkingDirectory(workDir);
removeDirectory(workDir);
}

@Override
protected void processDebug(AbstractResultContext<DynamicSecurityAnalysisRunContext> resultContext) {
// copy all content from working directory into debug directory
DynamicSecurityAnalysisRunContext runContext = resultContext.getRunContext();
if (runContext.getWorkDir() != null && runContext.getDebugDir() != null) {
try {
FileUtil.copyDir(runContext.getWorkDir(), runContext.getDebugDir());
} catch (IOException e) {
LOGGER.error("{}: Error occurred while copying directory {} to directory {} => {}",
getComputationType(), runContext.getWorkDir().toAbsolutePath(), runContext.getDebugDir().toAbsolutePath(), e.getMessage());
}
}
super.processDebug(resultContext);
}

private Path createWorkingDirectory() {
Path workDir;
Path localDir = getComputationManager().getLocalDir();
try {
workDir = Files.createTempDirectory(localDir, "dynamic_security_analysis_");
workDir = Files.createTempDirectory(localDir, buildComputationDirPrefix());
} catch (IOException e) {
throw new DynamicSecurityAnalysisException(DUMP_FILE_ERROR, String.format("Error occurred while creating a working directory inside the local directory %s",
localDir.toAbsolutePath()));
}
return workDir;
}

private void removeWorkingDirectory(Path workDir) {
if (workDir != null) {
try {
FileUtil.removeDir(workDir);
} catch (IOException e) {
LOGGER.error(String.format("%s: Error occurred while cleaning working directory at %s", getComputationType(), workDir.toAbsolutePath()), e);
}
} else {
LOGGER.info("{}: No working directory to clean", getComputationType());
}
}

// --- TODO remove these reports when powsybl-dynawo implements --- //
private static void enrichContingenciesTimelineReport(SecurityAnalysisReport securityAnalysisReport, ReportNode reportNode) {
for (PostContingencyResult postContingencyResult : securityAnalysisReport.getResult().getPostContingencyResults()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.powsybl.commons.io.FileUtil;
import com.powsybl.dynamicsimulation.DynamicSimulationParameters;
import com.powsybl.dynamicsimulation.DynamicSimulationProvider;
import com.powsybl.dynawo.DumpFileParameters;
Expand Down Expand Up @@ -57,7 +56,8 @@ public ParametersService(@Value("${dynamic-security-analysis.default-provider}")
public DynamicSecurityAnalysisRunContext createRunContext(UUID networkUuid, String variantId, String receiver,
String provider, ReportInfos reportInfos, String userId,
UUID dynamicSimulationResultUuid,
UUID dynamicSecurityAnalysisParametersUuid) {
UUID dynamicSecurityAnalysisParametersUuid,
boolean debug) {

// get parameters from the local database
DynamicSecurityAnalysisParametersInfos dynamicSecurityAnalysisParametersInfos = getParameters(dynamicSecurityAnalysisParametersUuid);
Expand All @@ -70,6 +70,7 @@ public DynamicSecurityAnalysisRunContext createRunContext(UUID networkUuid, Stri
.reportInfos(reportInfos)
.userId(userId)
.parameters(dynamicSecurityAnalysisParametersInfos)
.debug(debug)
.build();
runContext.setDynamicSimulationResultUuid(dynamicSimulationResultUuid);

Expand All @@ -93,11 +94,9 @@ public DynamicSecurityAnalysisRunContext createRunContext(UUID networkUuid, Stri
// --- Dynamic simulation result related methods --- //

public void setupDumpParameters(Path workDir, DynamicSimulationParameters dynamicSimulationParameters, byte[] zippedOutputState) {
Path dumpDir = workDir.resolve("dump");
FileUtil.createDirectory(dumpDir);
Path dumpFile = unZipDumpFile(dumpDir, zippedOutputState);
Path dumpFile = unZipDumpFile(workDir, zippedOutputState);
DynawoSimulationParameters dynawoSimulationParameters = dynamicSimulationParameters.getExtension(DynawoSimulationParameters.class);
dynawoSimulationParameters.setDumpFileParameters(DumpFileParameters.createImportDumpFileParameters(dumpDir, dumpFile.getFileName().toString()));
dynawoSimulationParameters.setDumpFileParameters(DumpFileParameters.createImportDumpFileParameters(workDir, dumpFile.getFileName().toString()));
}

private Path unZipDumpFile(Path dumpDir, byte[] zippedOutputState) {
Expand Down
Loading
Loading