Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,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.securityanalysis.server.computation.utils.ReportContext;
import org.gridsuite.securityanalysis.server.dto.*;
import org.gridsuite.securityanalysis.server.service.SecurityAnalysisParametersService;
import org.gridsuite.securityanalysis.server.service.SecurityAnalysisResultService;
Expand All @@ -35,7 +36,7 @@
import java.util.List;
import java.util.UUID;

import static org.gridsuite.securityanalysis.server.service.NotificationService.HEADER_USER_ID;
import static org.gridsuite.securityanalysis.server.computation.service.NotificationService.HEADER_USER_ID;
import static org.springframework.http.MediaType.*;

/**
Expand Down Expand Up @@ -77,7 +78,7 @@ public ResponseEntity<SecurityAnalysisResult> run(@Parameter(description = "Netw
@Parameter(description = "parametersUuid") @RequestParam(name = "parametersUuid", required = false) UUID parametersUuid,
@Parameter(description = "loadFlow parameters uuid") @RequestParam(name = "loadFlowParametersUuid") UUID loadFlowParametersUuid,
@RequestHeader(HEADER_USER_ID) String userId) {
SecurityAnalysisResult result = workerService.run(securityAnalysisParametersService.createRunContext(networkUuid, variantId, new RunContextParametersInfos(contigencyListNames, parametersUuid, loadFlowParametersUuid), null, new ReportInfos(reportUuid, reporterId, reportType), userId));
SecurityAnalysisResult result = workerService.run(securityAnalysisParametersService.createRunContext(networkUuid, variantId, new RunContextParametersInfos(contigencyListNames, parametersUuid, loadFlowParametersUuid), null, new ReportContext(reportUuid, reporterId, reportType), userId));
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(result);
}

Expand All @@ -103,7 +104,7 @@ public ResponseEntity<UUID> runAndSave(@Parameter(description = "Network UUID")
variantId,
new RunContextParametersInfos(contigencyListNames, parametersUuid, loadFlowParametersUuid),
receiver,
new ReportInfos(reportUuid, reporterId, reportType),
new ReportContext(reportUuid, reporterId, reportType),
userId
)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2024, 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.securityanalysis.server.computation.service;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import lombok.NonNull;

/**
* @author Mathieu Deharbe <mathieu.deharbe at rte-france.com
* @param <R> powsybl Result class specific to the computation
* @param <P> powsybl and gridsuite parameters specifics to the computation
*/
public abstract class AbstractComputationObserver<R, P> {
protected static final String OBSERVATION_PREFIX = "app.computation.";
protected static final String PROVIDER_TAG_NAME = "provider";
protected static final String TYPE_TAG_NAME = "type";
protected static final String STATUS_TAG_NAME = "status";
protected static final String COMPUTATION_COUNTER_NAME = OBSERVATION_PREFIX + "count";
protected final ObservationRegistry observationRegistry;
protected final MeterRegistry meterRegistry;

protected AbstractComputationObserver(@NonNull ObservationRegistry observationRegistry, @NonNull MeterRegistry meterRegistry) {
this.observationRegistry = observationRegistry;
this.meterRegistry = meterRegistry;
}

protected abstract String getComputationType();

protected Observation createObservation(String name, AbstractComputationRunContext<P> runContext) {
return Observation.createNotStarted(OBSERVATION_PREFIX + name, observationRegistry)
.lowCardinalityKeyValue(PROVIDER_TAG_NAME, runContext.getProvider())
.lowCardinalityKeyValue(TYPE_TAG_NAME, getComputationType());
}

public <E extends Throwable> void observe(String name, AbstractComputationRunContext<P> runContext, Observation.CheckedRunnable<E> callable) throws E {
createObservation(name, runContext).observeChecked(callable);
}

public <T, E extends Throwable> T observe(String name, AbstractComputationRunContext<P> runContext, Observation.CheckedCallable<T, E> callable) throws E {
return createObservation(name, runContext).observeChecked(callable);
}

public <T extends R, E extends Throwable> T observeRun(
String name, AbstractComputationRunContext<P> runContext, Observation.CheckedCallable<T, E> callable) throws E {
T result = createObservation(name, runContext).observeChecked(callable);
incrementCount(runContext, result);
return result;
}

private void incrementCount(AbstractComputationRunContext<P> runContext, R result) {
Counter.builder(COMPUTATION_COUNTER_NAME)
.tag(PROVIDER_TAG_NAME, runContext.getProvider())
.tag(TYPE_TAG_NAME, getComputationType())
.tag(STATUS_TAG_NAME, getResultStatus(result))
.register(meterRegistry)
.increment();
}

protected abstract String getResultStatus(R res);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2024, 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.securityanalysis.server.computation.service;

import java.util.List;
import java.util.UUID;

/**
* @author Mathieu Deharbe <mathieu.deharbe at rte-france.com
* @param <S> status specific to the computation
*/
public abstract class AbstractComputationResultService<S> {

public abstract void insertStatus(List<UUID> resultUuids, S status);

public abstract void delete(UUID resultUuid);

public abstract void deleteAll();

public abstract S findStatus(UUID resultUuid);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2024, 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.securityanalysis.server.computation.service;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.gridsuite.securityanalysis.server.computation.utils.ReportContext;

import java.util.UUID;

/**
* @author Mathieu Deharbe <mathieu.deharbe at rte-france.com
* @param <P> parameters structure specific to the computation
*/
@Getter
@AllArgsConstructor
public abstract class AbstractComputationRunContext<P> {
private final UUID networkUuid;
private final String variantId;
private final String receiver;
private final ReportContext reportContext;
private final String userId;
@Setter protected String provider;
@Setter protected P parameters;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright (c) 2024, 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.securityanalysis.server.computation.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
* @author Mathieu Deharbe <mathieu.deharbe at rte-france.com
* @param <R> run context specific to a computation, including parameters
* @param <T> run service specific to a computation
* @param <S> enum status specific to a computation
*/
public abstract class AbstractComputationService<R extends AbstractComputationRunContext, T extends AbstractComputationResultService<S>, S> {

protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractComputationService.class);

protected ObjectMapper objectMapper;
protected NotificationService notificationService;
@Getter
protected String defaultProvider;

protected UuidGeneratorService uuidGeneratorService;
protected T resultService;

protected AbstractComputationService(NotificationService notificationService,
T resultService,
ObjectMapper objectMapper,
UuidGeneratorService uuidGeneratorService,
String defaultProvider) {
this.notificationService = Objects.requireNonNull(notificationService);
this.objectMapper = Objects.requireNonNull(objectMapper);
this.uuidGeneratorService = Objects.requireNonNull(uuidGeneratorService);
this.defaultProvider = Objects.requireNonNull(defaultProvider);
this.resultService = Objects.requireNonNull(resultService);
}

public void stop(UUID resultUuid, String receiver) {
notificationService.sendCancelMessage(new CancelContext(resultUuid, receiver).toMessage());
}

public abstract List<String> getProviders();

public abstract UUID runAndSaveResult(R runContext);

public void setStatus(List<UUID> resultUuids, S status) {
resultService.insertStatus(resultUuids, status);
}

public void deleteResult(UUID resultUuid) {
resultService.delete(resultUuid);
}

public void deleteResults() {
resultService.deleteAll();
}

public S getStatus(UUID resultUuid) {
return resultService.findStatus(resultUuid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright (c) 2023, 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.securityanalysis.server.computation.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;

import java.io.UncheckedIOException;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import static org.gridsuite.securityanalysis.server.computation.service.NotificationService.*;

/**
* @author Mathieu Deharbe <mathieu.deharbe at rte-france.com
* @param <R> run context specific to a computation, including parameters
*/
@Getter
public abstract class AbstractResultContext<R extends AbstractComputationRunContext<?>> {

protected static final String RESULT_UUID_HEADER = "resultUuid";

protected static final String NETWORK_UUID_HEADER = "networkUuid";

protected static final String REPORT_UUID_HEADER = "reportUuid";

public static final String VARIANT_ID_HEADER = "variantId";

public static final String REPORTER_ID_HEADER = "reporterId";

public static final String REPORT_TYPE_HEADER = "reportType";

protected static final String MESSAGE_ROOT_NAME = "parameters";

protected final UUID resultUuid;

protected final R runContext;

protected AbstractResultContext(UUID resultUuid, R runContext) {
this.resultUuid = Objects.requireNonNull(resultUuid);
this.runContext = Objects.requireNonNull(runContext);
}

public Message<String> toMessage(ObjectMapper objectMapper) {
String parametersJson;
try {
parametersJson = objectMapper.writeValueAsString(runContext.getParameters());
} catch (JsonProcessingException e) {
throw new UncheckedIOException(e);
}
return MessageBuilder.withPayload(parametersJson)
.setHeader(RESULT_UUID_HEADER, resultUuid.toString())
.setHeader(NETWORK_UUID_HEADER, runContext.getNetworkUuid().toString())
.setHeader(VARIANT_ID_HEADER, runContext.getVariantId())
.setHeader(HEADER_RECEIVER, runContext.getReceiver())
.setHeader(HEADER_PROVIDER, runContext.getProvider())
.setHeader(HEADER_USER_ID, runContext.getUserId())
.setHeader(REPORT_UUID_HEADER, runContext.getReportContext().getReportId() != null ? runContext.getReportContext().getReportId().toString() : null)
.setHeader(REPORTER_ID_HEADER, runContext.getReportContext().getReportName())
.setHeader(REPORT_TYPE_HEADER, runContext.getReportContext().getReportType())
.copyHeaders(getSpecificMsgHeaders())
.build();
}

public abstract Map<String, String> getSpecificMsgHeaders();
}
Loading