Skip to content
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

Mockable time in messages #55

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
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
Next Next commit
generic computation classes (short circuit code version)
Signed-off-by: Mathieu DEHARBE <mathieu.deharbe@rte-france.com>
  • Loading branch information
Mathieu-Deharbe committed May 30, 2024
commit 6cf2c9271fbd839ea269df2884119c474147430d
41 changes: 40 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
@@ -38,7 +38,6 @@
</developers>

<properties>
<java.version>11</java.version>
<powsybl-dependencies.version>2024.1.0</powsybl-dependencies.version>
<springboot.version>3.1.2</springboot.version>
</properties>
@@ -130,5 +129,45 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version> <!-- TODO : probablement à retirer ou déplacer dans un truc général-->
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<version>4.0.3</version> <!-- TODO : probablement à retirer ou déplacer dans un truc général-->
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-commons</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-computation</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-computation-local</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-network-store-client</artifactId>
<version>1.11.0</version> <!-- TODO : probablement à retirer ou déplacer dans un truc général-->
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* 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 com.powsybl.ws.commons.computation.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;

import java.util.UUID;

/**
* @author Florent MILLOT <florent.millot at rte-france.com>
*/
@Builder
@Schema(description = "Report infos")
public record ReportInfos(
UUID reportUuid,
String reporterId,
String computationType
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* 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 com.powsybl.ws.commons.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.Getter;
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
*/
@Getter
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";

private final ObservationRegistry observationRegistry;
private 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) {
Observation observation = Observation.createNotStarted(OBSERVATION_PREFIX + name, observationRegistry)
.lowCardinalityKeyValue(TYPE_TAG_NAME, getComputationType());
if (runContext.getProvider() != null) {
observation.lowCardinalityKeyValue(PROVIDER_TAG_NAME, runContext.getProvider());
}
return observation;
}

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 builder =
Counter.builder(COMPUTATION_COUNTER_NAME);
if (runContext.getProvider() != null) {
builder.tag(PROVIDER_TAG_NAME, runContext.getProvider());
}
builder.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 com.powsybl.ws.commons.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,46 @@
/**
* 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 com.powsybl.ws.commons.computation.service;

import com.powsybl.commons.report.ReportNode;
import com.powsybl.iidm.network.Network;
import com.powsybl.ws.commons.computation.dto.ReportInfos;
import lombok.Getter;
import lombok.Setter;

import java.util.UUID;

/**
* @author Mathieu Deharbe <mathieu.deharbe at rte-france.com>
* @param <P> parameters structure specific to the computation
*/
@Getter
@Setter
public abstract class AbstractComputationRunContext<P> {
private final UUID networkUuid;
private final String variantId;
private final String receiver;
private final ReportInfos reportInfos;
private final String userId;
private String provider;
private P parameters;
private ReportNode reportNode;
private Network network;

protected AbstractComputationRunContext(UUID networkUuid, String variantId, String receiver, ReportInfos reportInfos,
String userId, String provider, P parameters) {
this.networkUuid = networkUuid;
this.variantId = variantId;
this.receiver = receiver;
this.reportInfos = reportInfos;
this.userId = userId;
this.provider = provider;
this.parameters = parameters;
this.reportNode = ReportNode.NO_OP;
this.network = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* 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 com.powsybl.ws.commons.computation.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import org.springframework.util.CollectionUtils;

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 ObjectMapper objectMapper;
protected NotificationService notificationService;
@Getter
private final 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 = objectMapper;
this.uuidGeneratorService = Objects.requireNonNull(uuidGeneratorService);
this.defaultProvider = 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 deleteResult(UUID resultUuid) {
resultService.delete(resultUuid);
}

public void deleteResults(List<UUID> resultUuids) {
if (!CollectionUtils.isEmpty(resultUuids)) {
resultUuids.forEach(resultService::delete);
} else {
deleteResults();
}
}

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

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

public S getStatus(UUID resultUuid) {
return resultService.findStatus(resultUuid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* 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 com.powsybl.ws.commons.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 com.powsybl.ws.commons.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";

private final UUID resultUuid;
private 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.getReportInfos().reportUuid() != null ? runContext.getReportInfos().reportUuid().toString() : null)
.setHeader(REPORTER_ID_HEADER, runContext.getReportInfos().reporterId())
.setHeader(REPORT_TYPE_HEADER, runContext.getReportInfos().computationType())
.copyHeaders(getSpecificMsgHeaders())
.build();
}

protected Map<String, String> getSpecificMsgHeaders() {
return Map.of();
}
}
Loading