Faster module searches (CPS-2190 #3) 90/137790/1
authordanielhanrahan <daniel.hanrahan@est.tech>
Fri, 26 Apr 2024 09:09:54 +0000 (10:09 +0100)
committerdanielhanrahan <daniel.hanrahan@est.tech>
Fri, 26 Apr 2024 09:48:29 +0000 (10:48 +0100)
This greatly improves performance of module searches by eliminating
unneeded SQL queries via Hibernate lazy fetching.

Issue-ID: CPS-2190
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: Ie9e65017d0027366456f1741cc37b10679317b25

cps-ri/src/main/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/ModuleQueryPerfTest.groovy

index d697fd5..56a0464 100755 (executable)
@@ -131,11 +131,10 @@ public class CpsAdminPersistenceServiceImpl implements CpsAdminPersistenceServic
     }
 
     @Override
-    public Collection<Anchor> queryAnchors(final String dataspaceName, final Collection<String> inputModuleNames) {
+    public Collection<String> queryAnchorNames(final String dataspaceName, final Collection<String> inputModuleNames) {
         final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
-        final Collection<AnchorEntity> anchorEntities = anchorRepository
-            .getAnchorsByDataspaceIdAndModuleNames(dataspaceEntity.getId(), inputModuleNames, inputModuleNames.size());
-        return anchorEntities.stream().map(CpsAdminPersistenceServiceImpl::toAnchor).collect(Collectors.toSet());
+        return anchorRepository.getAnchorNamesByDataspaceIdAndModuleNames(dataspaceEntity.getId(), inputModuleNames,
+                inputModuleNames.size());
     }
 
     @Override
index 19646c5..d78a016 100755 (executable)
@@ -72,7 +72,7 @@ public interface AnchorRepository extends JpaRepository<AnchorEntity, Long> {
 
     @Query(value = """
             SELECT
-                anchor.*
+                anchor.name
             FROM
                      yang_resource
                 JOIN schema_set_yang_resources ON schema_set_yang_resources.yang_resource_id = yang_resource.id
@@ -89,15 +89,15 @@ public interface AnchorRepository extends JpaRepository<AnchorEntity, Long> {
             HAVING
                 COUNT(DISTINCT module_name) = :sizeOfModuleNames
             """, nativeQuery = true)
-    Collection<AnchorEntity> getAnchorsByDataspaceIdAndModuleNames(@Param("dataspaceId") int dataspaceId,
-                                                                   @Param("moduleNames") String[] moduleNames,
-                                                                   @Param("sizeOfModuleNames") int sizeOfModuleNames);
+    Collection<String> getAnchorNamesByDataspaceIdAndModuleNames(@Param("dataspaceId") int dataspaceId,
+                                                                 @Param("moduleNames") String[] moduleNames,
+                                                                 @Param("sizeOfModuleNames") int sizeOfModuleNames);
 
-    default Collection<AnchorEntity> getAnchorsByDataspaceIdAndModuleNames(final int dataspaceId,
-                                                                           final Collection<String> moduleNames,
-                                                                           final int sizeOfModuleNames) {
+    default Collection<String> getAnchorNamesByDataspaceIdAndModuleNames(final int dataspaceId,
+                                                                         final Collection<String> moduleNames,
+                                                                         final int sizeOfModuleNames) {
         final String[] moduleNamesArray = moduleNames.toArray(new String[0]);
-        return getAnchorsByDataspaceIdAndModuleNames(dataspaceId, moduleNamesArray, sizeOfModuleNames);
+        return getAnchorNamesByDataspaceIdAndModuleNames(dataspaceId, moduleNamesArray, sizeOfModuleNames);
     }
 
     @Modifying
index f09a795..aa9c45d 100644 (file)
@@ -21,7 +21,6 @@
 package org.onap.cps.api.impl;
 
 import java.util.Collection;
-import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.spi.CpsAdminPersistenceService;
@@ -87,8 +86,7 @@ public class CpsAnchorServiceImpl implements CpsAnchorService {
     @Override
     public Collection<String> queryAnchorNames(final String dataspaceName, final Collection<String> moduleNames) {
         cpsValidator.validateNameCharacters(dataspaceName);
-        final Collection<Anchor> anchors = cpsAdminPersistenceService.queryAnchors(dataspaceName, moduleNames);
-        return anchors.stream().map(Anchor::getName).collect(Collectors.toList());
+        return cpsAdminPersistenceService.queryAnchorNames(dataspaceName, moduleNames);
     }
 
     @Override
index 5a1810f..2b21619 100755 (executable)
@@ -107,7 +107,7 @@ public interface CpsAdminPersistenceService {
      * @return a collection of anchor names in the given dataspace. The schema set for each anchor must include all the
      *         given module names
      */
-    Collection<Anchor> queryAnchors(String dataspaceName, Collection<String> moduleNames);
+    Collection<String> queryAnchorNames(String dataspaceName, Collection<String> moduleNames);
 
     /**
      * Get an anchor in the given dataspace using the anchor name.
index 3546b81..c786538 100644 (file)
@@ -118,7 +118,7 @@ class CpsAnchorServiceImplSpec extends Specification {
 
     def 'Query all anchor identifiers for a dataspace and module names.'() {
         given: 'the persistence service is invoked with the expected parameters and returns a list of anchors'
-            mockCpsAdminPersistenceService.queryAnchors('some-dataspace-name', ['some-module-name']) >> [new Anchor(name:'some-anchor-identifier')]
+            mockCpsAdminPersistenceService.queryAnchorNames('some-dataspace-name', ['some-module-name']) >> ['some-anchor-identifier']
         when: 'query anchor names is called using a dataspace name and module name'
             def result = objectUnderTest.queryAnchorNames('some-dataspace-name', ['some-module-name'])
         then: 'get anchor identifiers returns the same anchor identifier returned by the persistence layer'
@@ -130,7 +130,7 @@ class CpsAnchorServiceImplSpec extends Specification {
     def 'Query all anchors with Module Names Not Found Exception in persistence layer.'() {
         given: 'the persistence layer throws a Module Names Not Found Exception'
             def originalException = new ModuleNamesNotFoundException('exception-ds', ['m1', 'm2'])
-            mockCpsAdminPersistenceService.queryAnchors(*_) >> { throw originalException}
+            mockCpsAdminPersistenceService.queryAnchorNames(*_) >> { throw originalException}
         when: 'attempt query anchors'
             objectUnderTest.queryAnchorNames('some-dataspace-name', [])
         then: 'the same exception is thrown (up)'
index 6efebd4..add931a 100644 (file)
@@ -86,11 +86,11 @@ class ModuleQueryPerfTest extends CpsPerfTestBase {
         and: 'operation completes with expected resource usage'
             recordAndAssertResourceUsage("Query for anchors with ${scenario}",
                     expectedTimeInSeconds, resourceMeter.totalTimeInSeconds,
-                    150, resourceMeter.totalMemoryUsageInMB)
+                    5, resourceMeter.totalMemoryUsageInMB)
         where: 'the following parameters are used'
             scenario         | yangModuleName || expectedTimeInSeconds
-            '1 KB module'    | 'module0'      || 3
-            '1000 KB module' | 'module1'      || 3
+            '1 KB module'    | 'module0'      || 0.05
+            '1000 KB module' | 'module1'      || 0.05
     }
 
     def 'Module query - Clean up test data.'() {