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
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
33 changes: 32 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@
</developers>

<properties>
<java.version>11</java.version>
<powsybl-dependencies.version>2024.1.0</powsybl-dependencies.version>
<springboot.version>3.1.2</springboot.version>
<spring-cloud-stream.version>4.0.3</spring-cloud-stream.version>
<powsybl-network-store-client.version>1.12.0</powsybl-network-store-client.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -92,6 +93,12 @@
<artifactId>spring-boot-starter-tomcat</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<version>${spring-cloud-stream.version}</version>
<optional>true</optional>
</dependency>

<!-- APT libraries -->
<dependency>
Expand All @@ -110,6 +117,7 @@
<scope>provided</scope>
</dependency>

<!-- test -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
Expand All @@ -124,11 +132,34 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-network-store-client</artifactId>
<version>${powsybl-network-store-client.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.powsybl.ws.commons.computation;

import com.fasterxml.jackson.databind.InjectableValues;
import com.powsybl.commons.report.ReportNodeDeserializer;
import com.powsybl.commons.report.ReportNodeJsonModule;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Clock;

@Configuration
public class ComputationConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.modulesToInstall(new ReportNodeJsonModule())
.postConfigurer(objMapper -> objMapper.setInjectableValues(new InjectableValues.Std().addValue(ReportNodeDeserializer.DICTIONARY_VALUE_ID, null)));
}

@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
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,77 @@
/**
* 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.AccessLevel;
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(AccessLevel.PROTECTED)
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,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.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;
protected UuidGeneratorService uuidGeneratorService;
protected T resultService;
@Getter
private final String defaultProvider;

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);
}
}
Loading