Skip to content

Commit

Permalink
improve usage of CarbonAwareComputingAPI
Browse files Browse the repository at this point in the history
- correct use of windowsSize as duration of the task
- improve response mapping with a check whether the optimal timeframe is in the future
- // TODO work around the limitation that the api does not provide a value for the earliestForecastedValue
  • Loading branch information
maxbehr801 committed Nov 29, 2024
1 parent 8aaeda0 commit 83146ad
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@ public class CarbonAwareComputingApiClient implements CarbonEmissionQuery {
@Override
public EmissionTimeframe getEmissionTimeframe(Location location, ProcessDuration processDuration, ProcessDuration executiontime)
throws CarbonEmissionQueryException {
final int windowSizeMinutes = 5;
List<EmissionsForecast> emissionsForecast = null;
final String mappedLocation = locationMapper.mapLocation(location);
if (mappedLocation == null) {
throw new CarbonEmissionQueryException("The location is not known yet.");
}

try {
emissionsForecast = forecastApi.getBestExecutionTime(mappedLocation, null, processDuration.timeshiftFromNow(), windowSizeMinutes);
emissionsForecast = forecastApi.getBestExecutionTime(mappedLocation, null, processDuration.timeshiftFromNow(), executiontime.inMinutes());
} catch (Exception e) {
log.error("Error when calling the API for the optimal forecast", e);
throw new CarbonEmissionQueryException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@
import de.envite.greenbpm.carbonreductor.core.domain.model.emissionframe.ForecastedValue;
import de.envite.greenbpm.carbonreductor.core.domain.model.emissionframe.OptimalTime;

import java.time.OffsetDateTime;

public class CarbonAwareComputingMapper {

public EmissionTimeframe mapToDomain(EmissionsData emissionsData) {
// TODO keep in mind: cleanerEnergyInFuture will not work as expected with earliestForecastedValue 0.0
if (emissionsData.getTimestamp().isAfter(OffsetDateTime.now())) {
return new EmissionTimeframe(
new OptimalTime(emissionsData.getTimestamp()),
new EarliestForecastedValue(0.0),
new ForecastedValue(emissionsData.getValue())
);
}

return new EmissionTimeframe(
new OptimalTime(emissionsData.getTimestamp()),
new EarliestForecastedValue(emissionsData.getValue()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,18 @@ class CarbonAwareComputingApiClientTest {
private CarbonAwareComputingMapper carbonAwareComputingMapperMock;

static class Data {
final static Location location = Locations.FRANCE_CENTRAL.asLocation();
final static ProcessDuration PROCESS_DURATION = new ProcessDuration("PT5M");
final static ProcessDuration executiontime = new ProcessDuration("PT10M");
static final Location location = Locations.FRANCE_CENTRAL.asLocation();
static final ProcessDuration PROCESS_DURATION = new ProcessDuration("PT5M");
static final ProcessDuration executiontime = new ProcessDuration("PT10M");

final static EmissionTimeframe emissionTimeframe = new EmissionTimeframe(
static final EmissionTimeframe emissionTimeframe = new EmissionTimeframe(
new OptimalTime(java.time.OffsetDateTime.now().plusHours(3)),
new EarliestForecastedValue(200.6),
new ForecastedValue(0.0)
);
}

private static final String LOCATION = "de";
private static final int WINDOW_SIZE_MINUTES = 5;


@BeforeEach
void setUp() {
Expand All @@ -67,7 +65,7 @@ void should_call_api_and_map() throws Exception {
EmissionsData emissionsData = mock(EmissionsData.class);
when(emissionsForecast.getOptimalDataPoints()).thenReturn(List.of(emissionsData));
when(forecastApiMock.getBestExecutionTime(
eq(LOCATION), isNull(), any(OffsetDateTime.class), eq(WINDOW_SIZE_MINUTES))
eq(LOCATION), isNull(), any(OffsetDateTime.class), eq(Data.executiontime.inMinutes()))
).thenReturn(List.of(emissionsForecast));
when(carbonAwareComputingMapperMock.mapToDomain(emissionsData)).thenReturn(Data.emissionTimeframe);

Expand All @@ -77,7 +75,7 @@ void should_call_api_and_map() throws Exception {
}

@Test
void should_throw_if_location_unknown() throws Exception {
void should_throw_if_location_unknown() {
when(locationMapperMock.mapLocation(any(Location.class))).thenReturn(null);

assertThatThrownBy(() -> classUnderTest.getEmissionTimeframe(Data.location, Data.PROCESS_DURATION, Data.executiontime))
Expand All @@ -91,7 +89,7 @@ void should_throw_if_location_unknown() throws Exception {
void should_throw_if_no_element_in_list_response() throws Exception {
when(locationMapperMock.mapLocation(any(Location.class))).thenReturn(LOCATION);
when(forecastApiMock.getBestExecutionTime(
eq(LOCATION), isNull(), any(OffsetDateTime.class), eq(WINDOW_SIZE_MINUTES))
eq(LOCATION), isNull(), any(OffsetDateTime.class), eq(Data.executiontime.inMinutes()))
).thenReturn(List.of());

assertThatThrownBy(() -> classUnderTest.getEmissionTimeframe(Data.location, Data.PROCESS_DURATION, Data.executiontime))
Expand All @@ -106,7 +104,7 @@ void should_throw_if_no_element_in_inner_list_response() throws Exception {
EmissionsForecast emissionsForecast = mock(EmissionsForecast.class);
when(emissionsForecast.getOptimalDataPoints()).thenReturn(List.of());
when(forecastApiMock.getBestExecutionTime(
eq(LOCATION), isNull(), any(OffsetDateTime.class), eq(WINDOW_SIZE_MINUTES))
eq(LOCATION), isNull(), any(OffsetDateTime.class), eq(Data.executiontime.inMinutes()))
).thenReturn(List.of(emissionsForecast));

assertThatThrownBy(() -> classUnderTest.getEmissionTimeframe(Data.location, Data.PROCESS_DURATION, Data.executiontime))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void should_throw_if_optimal_time_is_null() {
}

@Test
void should_throw_if_rating_is_null() {
void should_throw_if_earliestForecastedValue_is_null() {
assertThatThrownBy(() -> new EmissionTimeframe(optimalTime, null, forecastedValue))
.isInstanceOf(InvariantException .class);
}
Expand All @@ -54,15 +54,15 @@ void should_throw_if_forecast_is_null() {
class CleanEnergyInFutureCalculation {

@Test
void should_return_false_if_rating_is_smaller_than_forecast() {
ForecastedValue forecastedValue = new ForecastedValue(500.0);
EmissionTimeframe emissionTimeframe = new EmissionTimeframe(optimalTime, earliestForecastedValue, forecastedValue);
void should_return_false_if_earliestForecastedValue_is_smaller_than_forecast() {
ForecastedValue higherForecastedValue = new ForecastedValue(500.0);
EmissionTimeframe emissionTimeframe = new EmissionTimeframe(optimalTime, earliestForecastedValue, higherForecastedValue);

assertThat(emissionTimeframe.isCleanerEnergyInFuture()).isFalse();
}

@Test
void should_return_true_if_rating_is_greater_than_forecast() {
void should_return_true_if_earliestForecastedValue_is_greater_than_forecast() {
EmissionTimeframe emissionTimeframe = new EmissionTimeframe(optimalTime, earliestForecastedValue, forecastedValue);

assertThat(emissionTimeframe.isCleanerEnergyInFuture()).isTrue();
Expand Down

0 comments on commit 83146ad

Please sign in to comment.