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