Skip to content

Commit 62c0036

Browse files
committed
[conluz-100] Changed job that sync todays production to run only between 6 and 22. Created a new job to get production data from previous days. Adapted method that sync with Huawei to get hourly production between date interval to log in case of failed response
1 parent bfe0c61 commit 62c0036

File tree

7 files changed

+262
-68
lines changed

7 files changed

+262
-68
lines changed

src/main/java/org/lucoenergia/conluz/domain/production/huawei/sync/SyncHuaweiProductionService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.lucoenergia.conluz.domain.production.huawei.sync;
22

3+
import java.time.OffsetDateTime;
4+
35
public interface SyncHuaweiProductionService {
46

57
/**
@@ -9,5 +11,5 @@ public interface SyncHuaweiProductionService {
911
*/
1012
void syncRealTimeProduction();
1113

12-
void syncHourlyProduction();
14+
void syncHourlyProduction(OffsetDateTime startDate, OffsetDateTime endDate);
1315
}

src/main/java/org/lucoenergia/conluz/infrastructure/production/huawei/get/GetHuaweiHourlyProductionRepositoryRest.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@ public GetHuaweiHourlyProductionRepositoryRest(ObjectMapper objectMapper, Huawei
5757
public List<HourlyProduction> getHourlyProductionByDateInterval(List<Plant> stations, OffsetDateTime startDate,
5858
OffsetDateTime endDate) {
5959

60-
if (startDate.isAfter(endDate)) {
61-
LOGGER.error("Start date is after end date. Start date: {}, end date: {}", startDate, endDate);
62-
return new ArrayList<>();
63-
}
64-
6560
List<HourlyProduction> result = new ArrayList<>();
6661

6762
if (stations == null || stations.isEmpty()) {
@@ -140,6 +135,14 @@ private List<HourlyProduction> processBody(String body) throws JsonProcessingExc
140135

141136
List<HourlyProduction> dataList = new ArrayList<>();
142137

138+
JsonNode failCode = root.get("failCode");
139+
JsonNode success = root.get("success");
140+
if (failCode != null && failCode.asInt() == 407) {
141+
throw new HuaweiException("Request frequency is too high");
142+
} else if (!success.asBoolean()) {
143+
throw new HuaweiException("Calling Huawei API failed. Fail code: " + failCode + ", message: " + dataNode.asText());
144+
}
145+
143146
if (!dataNode.isArray()) {
144147
return dataList;
145148
}

src/main/java/org/lucoenergia/conluz/infrastructure/production/huawei/sync/SyncHuaweiProductionServiceImpl.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.lucoenergia.conluz.domain.production.plant.Plant;
1212
import org.lucoenergia.conluz.infrastructure.production.huawei.get.GetHuaweiHourlyProductionRepositoryRest;
1313
import org.lucoenergia.conluz.infrastructure.production.huawei.get.GetHuaweiRealTimeProductionRepositoryRest;
14-
import org.lucoenergia.conluz.infrastructure.shared.time.DateConverter;
1514
import org.slf4j.Logger;
1615
import org.slf4j.LoggerFactory;
1716
import org.springframework.stereotype.Service;
@@ -30,19 +29,17 @@ public class SyncHuaweiProductionServiceImpl implements SyncHuaweiProductionServ
3029
private final GetHuaweiHourlyProductionRepositoryRest getHuaweiHourlyProductionRepositoryRest;
3130
private final GetEnergyStationRepository getEnergyStationRepository;
3231
private final GetHuaweiConfigRepository getHuaweiConfigRepository;
33-
private final DateConverter dateConverter;
3432

3533
public SyncHuaweiProductionServiceImpl(PersistHuaweiProductionRepository persistHuaweiProductionRepository,
3634
GetHuaweiRealTimeProductionRepositoryRest getHuaweiRealTimeProductionRepositoryRest,
3735
GetHuaweiHourlyProductionRepositoryRest getHuaweiHourlyProductionRepositoryRest,
3836
GetEnergyStationRepository getEnergyStationRepository,
39-
GetHuaweiConfigRepository getHuaweiConfigRepository, DateConverter dateConverter) {
37+
GetHuaweiConfigRepository getHuaweiConfigRepository) {
4038
this.persistHuaweiProductionRepository = persistHuaweiProductionRepository;
4139
this.getHuaweiRealTimeProductionRepositoryRest = getHuaweiRealTimeProductionRepositoryRest;
4240
this.getHuaweiHourlyProductionRepositoryRest = getHuaweiHourlyProductionRepositoryRest;
4341
this.getEnergyStationRepository = getEnergyStationRepository;
4442
this.getHuaweiConfigRepository = getHuaweiConfigRepository;
45-
this.dateConverter = dateConverter;
4643
}
4744

4845
/**
@@ -75,7 +72,12 @@ public void syncRealTimeProduction() {
7572
}
7673

7774
@Override
78-
public void syncHourlyProduction() {
75+
public void syncHourlyProduction(OffsetDateTime startDate, OffsetDateTime endDate) {
76+
77+
if (startDate.isAfter(endDate)) {
78+
LOGGER.error("Start date is after end date. Start date: {}, end date: {}", startDate, endDate);
79+
return;
80+
}
7981

8082
// Get Huawei configuration
8183
Optional<HuaweiConfig> huaweiConfig = getHuaweiConfigRepository.getHuaweiConfig();
@@ -91,13 +93,9 @@ public void syncHourlyProduction() {
9193
return;
9294
}
9395

94-
// Calculate date interval to get data
95-
OffsetDateTime today = dateConverter.now();
96-
OffsetDateTime todayMinusOneWeek = today.minusWeeks(1);
97-
9896
// Get the productions for every station
9997
List<HourlyProduction> productions = getHuaweiHourlyProductionRepositoryRest.getHourlyProductionByDateInterval(huaweiStations,
100-
todayMinusOneWeek, today);
98+
startDate, endDate);
10199

102100
// Persist the production data
103101
persistHuaweiProductionRepository.persistHourlyProduction(productions);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.lucoenergia.conluz.infrastructure.production.huawei.sync;
2+
3+
import org.lucoenergia.conluz.domain.production.huawei.sync.SyncHuaweiProductionService;
4+
import org.lucoenergia.conluz.infrastructure.shared.job.Job;
5+
import org.lucoenergia.conluz.infrastructure.shared.time.DateConverter;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
import org.springframework.scheduling.annotation.Scheduled;
9+
import org.springframework.stereotype.Component;
10+
11+
import java.time.OffsetDateTime;
12+
13+
@Component
14+
public class SyncPreviousDaysHuaweiHourlyProductionJob implements Job {
15+
16+
private static final Logger LOGGER = LoggerFactory.getLogger(SyncPreviousDaysHuaweiHourlyProductionJob.class);
17+
18+
private final SyncHuaweiProductionService syncHuaweiProductionService;
19+
private final DateConverter dateConverter;
20+
21+
public SyncPreviousDaysHuaweiHourlyProductionJob(SyncHuaweiProductionService syncHuaweiProductionService, DateConverter dateConverter) {
22+
this.syncHuaweiProductionService = syncHuaweiProductionService;
23+
this.dateConverter = dateConverter;
24+
}
25+
26+
/**
27+
* This method starts the Huawei hourly production sync process every hour at 5 minutes past the hour.
28+
*/
29+
@Override
30+
@Scheduled(cron = "0 0 1 * * *")
31+
public void run() {
32+
LOGGER.info("Huawei hourly production sync started...");
33+
34+
// Calculate date interval to get data
35+
OffsetDateTime today = dateConverter.now();
36+
OffsetDateTime todayMinusOneWeek = today.minusWeeks(1);
37+
38+
syncHuaweiProductionService.syncHourlyProduction(todayMinusOneWeek, today.minusDays(1));
39+
40+
LOGGER.info("...finished Huawei hourly sync.");
41+
}
42+
}

src/main/java/org/lucoenergia/conluz/infrastructure/production/huawei/sync/SyncHuaweiHourlyProductionJob.java renamed to src/main/java/org/lucoenergia/conluz/infrastructure/production/huawei/sync/SyncTodaysHuaweiHourlyProductionJob.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,39 @@
22

33
import org.lucoenergia.conluz.domain.production.huawei.sync.SyncHuaweiProductionService;
44
import org.lucoenergia.conluz.infrastructure.shared.job.Job;
5+
import org.lucoenergia.conluz.infrastructure.shared.time.DateConverter;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78
import org.springframework.scheduling.annotation.Scheduled;
89
import org.springframework.stereotype.Component;
910

11+
import java.time.OffsetDateTime;
12+
1013
@Component
11-
public class SyncHuaweiHourlyProductionJob implements Job {
14+
public class SyncTodaysHuaweiHourlyProductionJob implements Job {
1215

13-
private static final Logger LOGGER = LoggerFactory.getLogger(SyncHuaweiHourlyProductionJob.class);
16+
private static final Logger LOGGER = LoggerFactory.getLogger(SyncTodaysHuaweiHourlyProductionJob.class);
1417

1518
private final SyncHuaweiProductionService syncHuaweiProductionService;
19+
private final DateConverter dateConverter;
1620

17-
public SyncHuaweiHourlyProductionJob(SyncHuaweiProductionService syncHuaweiProductionService) {
21+
public SyncTodaysHuaweiHourlyProductionJob(SyncHuaweiProductionService syncHuaweiProductionService, DateConverter dateConverter) {
1822
this.syncHuaweiProductionService = syncHuaweiProductionService;
23+
this.dateConverter = dateConverter;
1924
}
2025

2126
/**
2227
* This method starts the Huawei hourly production sync process every hour at 5 minutes past the hour.
2328
*/
2429
@Override
25-
@Scheduled(cron = "0 5 * * * *")
30+
@Scheduled(cron = "0 5 6-22 * * *")
2631
public void run() {
2732
LOGGER.info("Huawei hourly production sync started...");
2833

29-
syncHuaweiProductionService.syncHourlyProduction();
34+
// Calculate date interval to get data
35+
OffsetDateTime today = dateConverter.now();
36+
37+
syncHuaweiProductionService.syncHourlyProduction(today, today);
3038

3139
LOGGER.info("...finished Huawei hourly sync.");
3240
}

src/test/java/org/lucoenergia/conluz/infrastructure/production/get/GetHuaweiHourlyProductionRepositoryRestTest.java

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.lucoenergia.conluz.domain.production.plant.Plant;
1111
import org.lucoenergia.conluz.domain.production.huawei.HourlyProduction;
1212
import org.lucoenergia.conluz.infrastructure.production.huawei.HuaweiAuthorizer;
13+
import org.lucoenergia.conluz.infrastructure.production.huawei.HuaweiException;
1314
import org.lucoenergia.conluz.infrastructure.production.huawei.get.GetHuaweiHourlyProductionRepositoryRest;
1415
import org.lucoenergia.conluz.infrastructure.shared.time.DateConverter;
1516
import org.lucoenergia.conluz.infrastructure.shared.time.TimeConfiguration;
@@ -24,6 +25,7 @@
2425
import java.util.List;
2526

2627
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
import static org.junit.jupiter.api.Assertions.assertThrows;
2729
import static org.junit.jupiter.api.Assertions.assertTrue;
2830
import static org.mockito.ArgumentMatchers.any;
2931
import static org.mockito.Mockito.when;
@@ -43,52 +45,70 @@ class GetHuaweiHourlyProductionRepositoryRestTest {
4345
new Plant.Builder().withCode("5D02E8B40AD342159AC8D8A2BCD4FAB5").build()
4446
);
4547

48+
private static final String RESPONSE_BODY_ACCESS_FREQUENCY_IS_TOO_HIGH = """
49+
{
50+
"data": "ACCESS_FREQUENCY_IS_TOO_HIGH",
51+
"failCode": 407,
52+
"params": null,
53+
"success": false
54+
}
55+
""";
56+
57+
private static final String RESPONSE_BODY_UNSUCCESSFUL = """
58+
{
59+
"data": "THERE_WAS_AN_ERROR",
60+
"failCode": 11,
61+
"params": null,
62+
"success": false
63+
}
64+
""";
65+
4666
private static final String RESPONSE_BODY_SUCCESSFULL = """
47-
{
48-
"success":true,
49-
"data":[
50-
{
51-
"dataItemMap":{
52-
"radiation_intensity":null,
53-
"theory_power":null,
54-
"inverter_power":0,
55-
"ongrid_power":null,
56-
"power_profit":0
57-
},
58-
"stationCode":"5D02E8B40AD342159AC8D8A2BCD4FAB5",
59-
"collectTime":1501862400000
60-
},
61-
{
62-
"dataItemMap":{
63-
"radiation_intensity":null,
64-
"theory_power":null,
65-
"inverter_power":10,
66-
"ongrid_power":null,
67-
"power_profit":5
68-
},
69-
"stationCode":"5D02E8B40AD342159AC8D8A2BCD4FAB5",
70-
"collectTime":1501866000000
71-
},
72-
{
73-
"dataItemMap":{
74-
"radiation_intensity":500,
75-
"theory_power":12.5,
76-
"inverter_power":10,
77-
"ongrid_power":20,
78-
"power_profit":5
79-
},
80-
"stationCode":"BA4372D08E014822AB065017416F254C",
81-
"collectTime":1501873200000
82-
}
83-
],
84-
"failCode":0,
85-
"params":{
86-
"stationCodes":"BA4372D08E014822AB065017416F254C,5D02E8B40AD342159AC8D8A2BCD4FAB5",
87-
"currentTime":1750627686362
67+
{
68+
"success":true,
69+
"data":[
70+
{
71+
"dataItemMap":{
72+
"radiation_intensity":null,
73+
"theory_power":null,
74+
"inverter_power":0,
75+
"ongrid_power":null,
76+
"power_profit":0
77+
},
78+
"stationCode":"5D02E8B40AD342159AC8D8A2BCD4FAB5",
79+
"collectTime":1501862400000
80+
},
81+
{
82+
"dataItemMap":{
83+
"radiation_intensity":null,
84+
"theory_power":null,
85+
"inverter_power":10,
86+
"ongrid_power":null,
87+
"power_profit":5
88+
},
89+
"stationCode":"5D02E8B40AD342159AC8D8A2BCD4FAB5",
90+
"collectTime":1501866000000
8891
},
89-
"message":null
90-
}
91-
""";
92+
{
93+
"dataItemMap":{
94+
"radiation_intensity":500,
95+
"theory_power":12.5,
96+
"inverter_power":10,
97+
"ongrid_power":20,
98+
"power_profit":5
99+
},
100+
"stationCode":"BA4372D08E014822AB065017416F254C",
101+
"collectTime":1501873200000
102+
}
103+
],
104+
"failCode":0,
105+
"params":{
106+
"stationCodes":"BA4372D08E014822AB065017416F254C,5D02E8B40AD342159AC8D8A2BCD4FAB5",
107+
"currentTime":1750627686362
108+
},
109+
"message":null
110+
}
111+
""";
92112

93113
@BeforeEach
94114
void setUp() {
@@ -100,9 +120,8 @@ void setUp() {
100120
repositoryRest = new GetHuaweiHourlyProductionRepositoryRest(new ObjectMapper(), huaweiAuthorizer,
101121
conluzRestClientBuilder, dateConverter);
102122
}
103-
104-
105-
123+
124+
106125
@Test
107126
void getHourlyProduction_ByDateInterval_shouldCallServiceSevenTimesWhenDateRangeIsOneWeek() throws IOException {
108127
// Given
@@ -133,6 +152,40 @@ void getHourlyProduction_ByDateInterval_shouldCallServiceSevenTimesWhenDateRange
133152
Mockito.verify(client, Mockito.times(8)).newCall(any());
134153
}
135154

155+
@Test
156+
void getHourlyProduction_ByDateInterval_shouldReturnExceptionWhenCallFailedDueToTooHighFrequencyAccess() throws IOException {
157+
// Given
158+
prepareSuccessfulResponse(RESPONSE_BODY_ACCESS_FREQUENCY_IS_TOO_HIGH);
159+
160+
// Calculate date interval to get data
161+
OffsetDateTime today = OffsetDateTime.now();
162+
OffsetDateTime todayMinusOneWeek = today.minusWeeks(1);
163+
164+
// When/Then
165+
HuaweiException exception = assertThrows(HuaweiException.class, () ->
166+
repositoryRest.getHourlyProductionByDateInterval(STATION_CODES, todayMinusOneWeek, today)
167+
);
168+
assertEquals("Request frequency is too high", exception.getMessage());
169+
170+
}
171+
172+
@Test
173+
void getHourlyProduction_ByDateInterval_shouldReturnExceptionWhenCallFailed() throws IOException {
174+
// Given
175+
prepareSuccessfulResponse(RESPONSE_BODY_UNSUCCESSFUL);
176+
177+
// Calculate date interval to get data
178+
OffsetDateTime today = OffsetDateTime.now();
179+
OffsetDateTime todayMinusOneWeek = today.minusWeeks(1);
180+
181+
// When/Then
182+
HuaweiException exception = assertThrows(HuaweiException.class, () ->
183+
repositoryRest.getHourlyProductionByDateInterval(STATION_CODES, todayMinusOneWeek, today)
184+
);
185+
assertEquals("Calling Huawei API failed. Fail code: 11, message: THERE_WAS_AN_ERROR", exception.getMessage());
186+
187+
}
188+
136189
@Test
137190
void getHourlyProduction_ByDateInterval_shouldReturnEmptyListWhenStartDateIsAfterEndDate() throws IOException {
138191
// Given

0 commit comments

Comments
 (0)