diff --git a/network-store-integration-test/pom.xml b/network-store-integration-test/pom.xml
index acf45e2c..7f28ae97 100644
--- a/network-store-integration-test/pom.xml
+++ b/network-store-integration-test/pom.xml
@@ -137,6 +137,11 @@
powsybl-ucte-converter
test
+
+ com.powsybl
+ powsybl-ieee-cdf-converter
+ test
+
diff --git a/network-store-integration-test/src/test/java/com/powsybl/network/store/integration/NetworkStoreIT.java b/network-store-integration-test/src/test/java/com/powsybl/network/store/integration/NetworkStoreIT.java
index 91f997b9..54d05723 100644
--- a/network-store-integration-test/src/test/java/com/powsybl/network/store/integration/NetworkStoreIT.java
+++ b/network-store-integration-test/src/test/java/com/powsybl/network/store/integration/NetworkStoreIT.java
@@ -17,6 +17,7 @@
import com.powsybl.entsoe.util.EntsoeArea;
import com.powsybl.entsoe.util.EntsoeAreaImpl;
import com.powsybl.entsoe.util.EntsoeGeographicalCode;
+import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.*;
import com.powsybl.iidm.network.test.*;
@@ -4071,4 +4072,62 @@ public void testFixNpeGetIdentifiable() {
assertEquals(2, twt2.getRatioTapChanger().getHighTapPosition());
}
}
+
+ @Test
+ public void testGetIdentifiablePerf() {
+ List lineIds;
+ try (NetworkStoreService service = createNetworkStoreService(randomServerPort)) {
+ Network network = IeeeCdfNetworkFactory.create14(service.getNetworkFactory());
+ lineIds = network.getLineStream().map(Identifiable::getId).toList();
+ service.flush(network);
+ }
+
+ RestClientMetrics metrics = new RestClientMetrics();
+ assertEquals(0, metrics.oneGetterCallCount);
+ assertEquals(0, metrics.allGetterCallCount);
+ try (NetworkStoreService service = createNetworkStoreService(metrics, randomServerPort)) {
+ Map networkIds = service.getNetworkIds();
+ UUID networkUuid = networkIds.keySet().stream().findFirst().orElseThrow();
+ Network network = service.getNetwork(networkUuid);
+ for (String id : lineIds.stream().limit(3).toList()) {
+ network.getIdentifiable(id);
+ }
+ assertEquals(4, metrics.oneGetterCallCount); // network + 3 lines
+ assertEquals(0, metrics.allGetterCallCount);
+
+ // we are under the threshold, we don't have downloaded the IDs of all existing identifiables
+ // and so on accessing a non-existing identifiable without having download the full collection
+ // need to access the server
+ network.getIdentifiable("FOO");
+ assertEquals(5, metrics.oneGetterCallCount);
+ assertEquals(0, metrics.allGetterCallCount);
+ }
+
+ metrics = new RestClientMetrics();
+ assertEquals(0, metrics.oneGetterCallCount);
+ assertEquals(0, metrics.allGetterCallCount);
+ try (NetworkStoreService service = createNetworkStoreService(metrics, randomServerPort)) {
+ Map networkIds = service.getNetworkIds();
+ UUID networkUuid = networkIds.keySet().stream().findFirst().orElseThrow();
+ Network network = service.getNetwork(networkUuid);
+
+ for (String id : lineIds.stream().limit(16).toList()) { // only the last one is not get
+ network.getIdentifiable(id);
+ }
+ assertEquals(17, metrics.oneGetterCallCount); // one network + 16 lines
+ assertEquals(0, metrics.allGetterCallCount);
+
+ // no more server access because we have downloaded the IDs of all existing identifiables and we know
+ // that FOO does not exist in the network
+ network.getIdentifiable("FOO");
+ assertEquals(17, metrics.oneGetterCallCount);
+ assertEquals(0, metrics.allGetterCallCount);
+
+ network.getIdentifiable("L13-14-1"); // the last one
+ // it is part of the network and thanks to all IDs download we know that we need to request it from the
+ // server
+ assertEquals(18, metrics.oneGetterCallCount);
+ assertEquals(0, metrics.allGetterCallCount);
+ }
+ }
}
diff --git a/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreController.java b/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreController.java
index f7127d04..b088dd0e 100644
--- a/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreController.java
+++ b/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreController.java
@@ -1423,4 +1423,15 @@ public ResponseEntity> getIdentifiable(
@Parameter(description = "Identifiable ID", required = true) @PathVariable("id") String id) {
return get(() -> repository.getIdentifiable(networkId, variantNum, id));
}
+
+ @GetMapping(value = "/{networkUuid}/{variantNum}/identifiables-ids", produces = APPLICATION_JSON_VALUE)
+ @Operation(summary = "Get all identifiables IDs")
+ @ApiResponses(value = {
+ @ApiResponse(responseCode = "200", description = "Successfully get the all identifiables IDs"),
+ @ApiResponse(responseCode = "404", description = "The network has not been found")
+ })
+ public List getIdentifiablesIds(@Parameter(description = "Network ID", required = true) @PathVariable("networkUuid") UUID networkUuid,
+ @Parameter(description = "Variant number", required = true) @PathVariable("variantNum") int variantNum) {
+ return repository.getIdentifiablesIds(networkUuid, variantNum);
+ }
}
diff --git a/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreRepository.java b/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreRepository.java
index a4d9acb1..fe45d307 100644
--- a/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreRepository.java
+++ b/network-store-server/src/main/java/com/powsybl/network/store/server/NetworkStoreRepository.java
@@ -146,6 +146,32 @@ public Optional> getNetwork(UUID uuid, int variantNu
}
}
+ public List getIdentifiablesIds(UUID networkUuid, int variantNum) {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ List ids = new ArrayList<>();
+ try (var connection = dataSource.getConnection()) {
+ for (String table : ELEMENT_TABLES) {
+ try (var preparedStmt = connection.prepareStatement(QueryCatalog.buildGetIdsQuery(table))) {
+ preparedStmt.setObject(1, networkUuid);
+ preparedStmt.setObject(2, variantNum);
+ try (ResultSet resultSet = preparedStmt.executeQuery()) {
+ while (resultSet.next()) {
+ ids.add(resultSet.getString(1));
+ }
+ }
+ }
+ }
+ } catch (SQLException e) {
+ throw new UncheckedSqlException(e);
+ }
+
+ stopwatch.stop();
+ LOGGER.info("Get identifiables IDs done in {} ms", stopwatch.elapsed(TimeUnit.MILLISECONDS));
+
+ return ids;
+ }
+
@FunctionalInterface
interface SqlExecutor {
diff --git a/network-store-server/src/main/java/com/powsybl/network/store/server/QueryCatalog.java b/network-store-server/src/main/java/com/powsybl/network/store/server/QueryCatalog.java
index 55987cd9..d8e3ae83 100644
--- a/network-store-server/src/main/java/com/powsybl/network/store/server/QueryCatalog.java
+++ b/network-store-server/src/main/java/com/powsybl/network/store/server/QueryCatalog.java
@@ -614,4 +614,11 @@ public static String buildDeleteTapChangerStepVariantEquipmentINQuery(int number
EQUIPMENT_ID_COLUMN + " in (" +
"?, ".repeat(numberOfValues - 1) + "?)";
}
+
+ public static String buildGetIdsQuery(String table) {
+ return "select " + ID_COLUMN +
+ " from " + table + " where " +
+ NETWORK_UUID_COLUMN + " = ? and " +
+ VARIANT_NUM_COLUMN + " = ?";
+ }
}
diff --git a/network-store-server/src/test/java/com/powsybl/network/store/server/NetworkStoreRepositoryTest.java b/network-store-server/src/test/java/com/powsybl/network/store/server/NetworkStoreRepositoryTest.java
index fa42e7f2..75c5c040 100644
--- a/network-store-server/src/test/java/com/powsybl/network/store/server/NetworkStoreRepositoryTest.java
+++ b/network-store-server/src/test/java/com/powsybl/network/store/server/NetworkStoreRepositoryTest.java
@@ -781,4 +781,25 @@ public void insertTapChangerStepsInThreeWindingsTranformerTest() {
assertNull(res3WTransformerB.getAttributes().getLeg(3).getRatioTapChangerAttributes());
assertEquals(1, res3WTransformerB.getAttributes().getLeg(3).getPhaseTapChangerAttributes().getSteps().size());
}
+
+ @Test
+ public void test() {
+ Resource line1 = Resource.lineBuilder()
+ .id("line1")
+ .attributes(LineAttributes.builder()
+ .voltageLevelId1("vl1")
+ .voltageLevelId2("vl2")
+ .build())
+ .build();
+ Resource load1 = Resource.loadBuilder()
+ .id("load1")
+ .attributes(LoadAttributes.builder()
+ .voltageLevelId("vl1")
+ .build())
+ .build();
+ networkStoreRepository.createLines(NETWORK_UUID, List.of(line1));
+ networkStoreRepository.createLoads(NETWORK_UUID, List.of(load1));
+ List identifiablesIds = networkStoreRepository.getIdentifiablesIds(NETWORK_UUID, Resource.INITIAL_VARIANT_NUM);
+ assertEquals(List.of("load1", "line1"), identifiablesIds);
+ }
}