Skip to content

Commit 75a5bfa

Browse files
authored
perf improvement get contingencies in one request (#135)
add endpoint to get a list of contengecies in one call --------- Signed-off-by: jamal-khey <[email protected]>
1 parent 65f05c4 commit 75a5bfa

File tree

4 files changed

+37
-39
lines changed

4 files changed

+37
-39
lines changed

src/main/java/org/gridsuite/securityanalysis/server/service/ActionsService.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,19 @@ public ActionsService(
4747
this.restTemplate = restTemplate;
4848
}
4949

50-
public List<ContingencyInfos> getContingencyList(String name, UUID networkUuid, String variantId) {
51-
Objects.requireNonNull(name);
50+
public List<ContingencyInfos> getContingencyList(List<String> ids, UUID networkUuid, String variantId) {
51+
Objects.requireNonNull(ids);
5252
Objects.requireNonNull(networkUuid);
53+
if (ids.isEmpty()) {
54+
throw new IllegalArgumentException("List 'ids' must not be null or empty");
55+
}
5356

5457
URI path = UriComponentsBuilder
55-
.fromPath(DELIMITER + ACTIONS_API_VERSION + "/contingency-lists/contingency-infos/{name}/export")
56-
.queryParam("networkUuid", networkUuid.toString())
57-
.queryParamIfPresent("variantId", Optional.ofNullable(variantId)).build(name);
58+
.fromPath(DELIMITER + ACTIONS_API_VERSION + "/contingency-lists/contingency-infos/export")
59+
.queryParam("networkUuid", networkUuid.toString())
60+
.queryParamIfPresent("variantId", Optional.ofNullable(variantId))
61+
.queryParam("ids", ids)
62+
.build().toUri();
5863

5964
return restTemplate.exchange(baseUri + path, HttpMethod.GET, null, new ParameterizedTypeReference<List<ContingencyInfos>>() { }).getBody();
6065
}

src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisWorkerService.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,9 @@ protected void preRun(SecurityAnalysisRunContext runContext) {
116116
LOGGER.info("Run security analysis on contingency lists: {}", runContext.getContingencyListNames().stream().map(LogUtils::sanitizeParam).toList());
117117

118118
List<ContingencyInfos> contingencies = observer.observe("contingencies.fetch", runContext,
119-
() -> runContext.getContingencyListNames()
120-
.stream()
121-
.flatMap(contingencyListName -> actionsService.getContingencyList(contingencyListName, runContext.getNetworkUuid(), runContext.getVariantId()).stream())
122-
.toList());
119+
() ->
120+
actionsService.getContingencyList(runContext.getContingencyListNames(), runContext.getNetworkUuid(), runContext.getVariantId())
121+
);
123122

124123
runContext.setContingencies(contingencies);
125124
}

src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
import java.nio.charset.StandardCharsets;
6666
import java.util.*;
6767
import java.util.concurrent.CountDownLatch;
68-
import java.util.stream.Collectors;
6968
import java.util.zip.ZipEntry;
7069
import java.util.zip.ZipInputStream;
7170

@@ -178,26 +177,6 @@ public void setUp() throws Exception {
178177
return network1;
179178
});
180179

181-
// action service mocking
182-
given(actionsService.getContingencyList(CONTINGENCY_LIST_NAME, NETWORK_UUID, VARIANT_1_ID))
183-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
184-
given(actionsService.getContingencyList(CONTINGENCY_LIST_NAME_VARIANT, NETWORK_UUID, VARIANT_3_ID))
185-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES_VARIANT.stream().map(ContingencyInfos::new).collect(Collectors.toList()));
186-
given(actionsService.getContingencyList(CONTINGENCY_LIST_NAME, NETWORK_UUID, VARIANT_2_ID))
187-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
188-
given(actionsService.getContingencyList(CONTINGENCY_LIST_NAME, NETWORK_UUID, null))
189-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
190-
given(actionsService.getContingencyList(CONTINGENCY_LIST2_NAME, NETWORK_UUID, VARIANT_1_ID))
191-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
192-
given(actionsService.getContingencyList(CONTINGENCY_LIST_NAME, NETWORK_STOP_UUID, VARIANT_2_ID))
193-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
194-
given(actionsService.getContingencyList(CONTINGENCY_LIST2_NAME, NETWORK_STOP_UUID, VARIANT_2_ID))
195-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
196-
given(actionsService.getContingencyList(CONTINGENCY_LIST_ERROR_NAME, NETWORK_UUID, VARIANT_1_ID))
197-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
198-
given(actionsService.getContingencyList(CONTINGENCY_LIST_NAME, NETWORK_STOP_UUID, VARIANT_TO_STOP_ID))
199-
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
200-
201180
// UUID service mocking to always generate the same result UUID
202181
given(uuidGeneratorService.generate()).willReturn(RESULT_UUID);
203182

@@ -684,7 +663,7 @@ public void runTestWithError() throws Exception {
684663
MvcResult mvcResult;
685664
String resultAsString;
686665

687-
given(actionsService.getContingencyList(CONTINGENCY_LIST_ERROR_NAME, NETWORK_UUID, VARIANT_1_ID))
666+
given(actionsService.getContingencyList(List.of(CONTINGENCY_LIST_ERROR_NAME), NETWORK_UUID, VARIANT_1_ID))
688667
.willThrow(new RuntimeException(ERROR_MESSAGE));
689668

690669
mvcResult = mockMvc.perform(post("/" + VERSION + "/networks/" + NETWORK_UUID + "/run-and-save?reportType=SecurityAnalysis&contingencyListName=" + CONTINGENCY_LIST_ERROR_NAME
@@ -735,6 +714,8 @@ public void runWithReportTestElementsNotFoundAndNotConnected() throws Exception
735714

736715
Network network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl());
737716
given(networkStoreService.getNetwork(NETWORK_UUID, PreloadingStrategy.COLLECTION)).willReturn(network);
717+
given(actionsService.getContingencyList(List.of(CONTINGENCY_LIST_NAME), NETWORK_UUID, null))
718+
.willReturn(SecurityAnalysisProviderMock.CONTINGENCIES);
738719

739720
mvcResult = mockMvc.perform(post("/" + VERSION + "/networks/" + NETWORK_UUID + "/run?reportType=SecurityAnalysis&contingencyListName=" + CONTINGENCY_LIST_NAME + "&provider=testProvider" + "&reportUuid=" + REPORT_UUID + "&reporterId=" + UUID.randomUUID() + "&loadFlowParametersUuid=" + UUID.randomUUID()).contentType(MediaType.APPLICATION_JSON)
740721
.header(HEADER_USER_ID, "testUserId")

src/test/java/org/gridsuite/securityanalysis/server/service/ActionsServiceTest.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class ActionsServiceTest {
5454
private static final String VARIANT_ID = "variant_id";
5555

5656
private static final String LIST_NAME = "myList";
57+
private static final String LIST_NAME_VARIANT = "myListVariant";
5758

5859
private static final String VERY_LARGE_LIST_NAME = "veryLargelist";
5960

@@ -92,25 +93,31 @@ private String initMockWebServer() throws IOException {
9293
String jsonExpected = objectMapper.writeValueAsString(List.of(CONTINGENCY));
9394
String veryLargeJsonExpected = objectMapper.writeValueAsString(createVeryLargeList());
9495
String jsonVariantExpected = objectMapper.writeValueAsString(List.of(CONTINGENCY_VARIANT));
96+
String jsonExpectedForList = objectMapper.writeValueAsString(List.of(CONTINGENCY, CONTINGENCY_VARIANT));
9597

9698
final Dispatcher dispatcher = new Dispatcher() {
9799
@NotNull
98100
@Override
99101
public MockResponse dispatch(RecordedRequest request) {
100102
String requestPath = Objects.requireNonNull(request.getPath());
101-
if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/%s/export?networkUuid=%s&variantId=%s", LIST_NAME, NETWORK_UUID, VARIANT_ID))) {
103+
104+
if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/export?networkUuid=%s&variantId=%s&ids=%s", NETWORK_UUID, VARIANT_ID, LIST_NAME))) {
102105
return new MockResponse().setResponseCode(HttpStatus.OK.value())
103106
.setBody(jsonVariantExpected)
104107
.addHeader("Content-Type", "application/json; charset=utf-8");
105-
} else if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/%s/export?networkUuid=%s", LIST_NAME, NETWORK_UUID))) {
108+
} else if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/export?networkUuid=%s&ids=%s", NETWORK_UUID, LIST_NAME))) {
106109
return new MockResponse().setResponseCode(HttpStatus.OK.value())
107110
.setBody(jsonExpected)
108111
.addHeader("Content-Type", "application/json; charset=utf-8");
109-
} else if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/%s/export?networkUuid=%s&variantId=%s", VERY_LARGE_LIST_NAME, NETWORK_UUID, VARIANT_ID))
110-
|| requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/%s/export?networkUuid=%s", VERY_LARGE_LIST_NAME, NETWORK_UUID))) {
112+
} else if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/export?networkUuid=%s&variantId=%s&ids=%s", NETWORK_UUID, VARIANT_ID, VERY_LARGE_LIST_NAME))
113+
|| requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/export?networkUuid=%s&ids=%s", NETWORK_UUID, VERY_LARGE_LIST_NAME))) {
111114
return new MockResponse().setResponseCode(HttpStatus.OK.value())
112115
.setBody(veryLargeJsonExpected)
113116
.addHeader("Content-Type", "application/json; charset=utf-8");
117+
} else if (requestPath.equals(String.format("/v1/contingency-lists/contingency-infos/export?networkUuid=%s&ids=%s&ids=%s", NETWORK_UUID, LIST_NAME, LIST_NAME_VARIANT))) {
118+
return new MockResponse().setResponseCode(HttpStatus.OK.value())
119+
.setBody(jsonExpectedForList)
120+
.addHeader("Content-Type", "application/json; charset=utf-8");
114121
} else {
115122
return new MockResponse().setResponseCode(HttpStatus.NOT_FOUND.value()).setBody("Path not supported: " + request.getPath());
116123
}
@@ -131,20 +138,26 @@ private List<ContingencyInfos> createVeryLargeList() {
131138

132139
@Test
133140
public void test() {
134-
List<ContingencyInfos> list = actionsService.getContingencyList(LIST_NAME, UUID.fromString(NETWORK_UUID), null);
141+
List<ContingencyInfos> list = actionsService.getContingencyList(List.of(LIST_NAME), UUID.fromString(NETWORK_UUID), null);
135142
list.forEach(contingencyInfos -> assertArrayEquals(List.of(WRONG_ID).toArray(new Object[0]), contingencyInfos.getNotFoundElements().toArray(new String[0])));
136143
assertEquals(Stream.of(CONTINGENCY).map(ContingencyInfos::getContingency).toList(), list.stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()));
137-
list = actionsService.getContingencyList(LIST_NAME, UUID.fromString(NETWORK_UUID), VARIANT_ID);
144+
list = actionsService.getContingencyList(List.of(LIST_NAME), UUID.fromString(NETWORK_UUID), VARIANT_ID);
138145
assertEquals(Stream.of(CONTINGENCY_VARIANT).map(ContingencyInfos::getContingency).toList(), list.stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()));
139146
}
140147

141148
@Test
142149
public void testVeryLargeList() {
143150
// DataBufferLimitException should not be thrown with this message : "Exceeded limit on max bytes to buffer : DATA_BUFFER_LIMIT"
144-
List<ContingencyInfos> list = actionsService.getContingencyList(VERY_LARGE_LIST_NAME, UUID.fromString(NETWORK_UUID), null);
151+
List<ContingencyInfos> list = actionsService.getContingencyList(List.of(VERY_LARGE_LIST_NAME), UUID.fromString(NETWORK_UUID), null);
145152
list.forEach(contingencyInfos -> assertArrayEquals(List.of().toArray(new Object[0]), contingencyInfos.getNotFoundElements().toArray(new String[0])));
146153
assertEquals(createVeryLargeList().stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()), list.stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()));
147-
list = actionsService.getContingencyList(VERY_LARGE_LIST_NAME, UUID.fromString(NETWORK_UUID), VARIANT_ID);
154+
list = actionsService.getContingencyList(List.of(VERY_LARGE_LIST_NAME), UUID.fromString(NETWORK_UUID), VARIANT_ID);
148155
assertEquals(createVeryLargeList().stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()), list.stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()));
149156
}
157+
158+
@Test
159+
public void testGetContingenciesByListOfIds() {
160+
List<ContingencyInfos> list = actionsService.getContingencyList(List.of(LIST_NAME, LIST_NAME_VARIANT), UUID.fromString(NETWORK_UUID), null);
161+
assertEquals(Stream.of(CONTINGENCY, CONTINGENCY_VARIANT).map(ContingencyInfos::getContingency).toList(), list.stream().map(ContingencyInfos::getContingency).collect(Collectors.toList()));
162+
}
150163
}

0 commit comments

Comments
 (0)