diff options
author | 2023-03-08 13:50:34 +0000 | |
---|---|---|
committer | 2023-03-13 14:30:46 +0000 | |
commit | 2e07b499eb798c19c8641078ff79364f9439a281 (patch) | |
tree | ec1287cb75f12d432da39d7736fd2cf723d77d13 /cps-ri/src/test/groovy | |
parent | 9a552aaf3dcd944a629aa30a3cb8122eb8ce7585 (diff) |
Fetch fragment entities using recursive SQL query
- Add SQL query that can fetch needed fragments to any given depth
- Update getFragmentEntities to use new query
- Remove now unused FragmentRepositoryMultiPathQuery
- Remove unused TempTableCreator method
- Result: getDataNodesForMultipleXpaths is up to 10 times faster
Issue-ID: CPS-1525
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: I07cbc9da5ab994ce7e0c2b02d7ca05089f05dab0
Diffstat (limited to 'cps-ri/src/test/groovy')
3 files changed, 42 insertions, 24 deletions
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy index 25f19f7a8..e60afa78d 100755 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy @@ -307,7 +307,7 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase { 'root xpath' | ["/"] || 7 'empty (root) xpath' | [""] || 7 'root and top-level xpaths' | ["/", "/parent-200", "/parent-201"] || 7 - 'root and child xpaths' | ["/", "/parent-200/child-201"] || 8 + 'root and child xpaths' | ["/", "/parent-200/child-201"] || 7 } @Sql([CLEAR_DATA, SET_DATA]) diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy index e74b4a745..3d7003d2a 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy @@ -26,6 +26,7 @@ import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.entities.AnchorEntity import org.onap.cps.spi.entities.DataspaceEntity import org.onap.cps.spi.entities.FragmentEntity +import org.onap.cps.spi.entities.FragmentExtract import org.onap.cps.spi.exceptions.ConcurrencyException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.model.DataNode @@ -150,9 +151,10 @@ class CpsDataPersistenceServiceSpec extends Specification { def 'Retrieving multiple data nodes.'() { given: 'fragment repository returns a collection of fragments' - def fragmentEntity1 = new FragmentEntity(xpath: '/xpath1', childFragments: []) - def fragmentEntity2 = new FragmentEntity(xpath: '/xpath2', childFragments: []) - mockFragmentRepository.findByAnchorAndMultipleCpsPaths(123, ['/xpath1', '/xpath2'] as Set<String>) >> [fragmentEntity1, fragmentEntity2] + mockFragmentRepository.findExtractsWithDescendants(123, ['/xpath1', '/xpath2'] as Set, _) >> [ + mockFragmentExtract(1, null, 123, '/xpath1', null), + mockFragmentExtract(2, null, 123, '/xpath2', null) + ] when: 'getting data nodes for 2 xpaths' def result = objectUnderTest.getDataNodesForMultipleXpaths('some-dataspace', 'some-anchor', ['/xpath1', '/xpath2'], FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) then: '2 data nodes are returned' @@ -203,8 +205,10 @@ class CpsDataPersistenceServiceSpec extends Specification { def 'update data node and descendants: #scenario'(){ given: 'the fragment repository returns fragment entities related to the xpath inputs' - mockFragmentRepository.findByAnchorAndMultipleCpsPaths(_, [] as Set) >> [] - mockFragmentRepository.findByAnchorAndMultipleCpsPaths(_, ['/test/xpath'] as Set) >> [new FragmentEntity(xpath: '/test/xpath', childFragments: [])] + mockFragmentRepository.findExtractsWithDescendants(_, [] as Set, _) >> [] + mockFragmentRepository.findExtractsWithDescendants(_, ['/test/xpath'] as Set, _) >> [ + mockFragmentExtract(1, null, 123, '/test/xpath', null) + ] when: 'replace data node tree' objectUnderTest.updateDataNodesAndDescendants('dataspaceName', 'anchorName', dataNodes) then: 'call fragment repository save all method' @@ -217,9 +221,10 @@ class CpsDataPersistenceServiceSpec extends Specification { def 'update data nodes and descendants'() { given: 'the fragment repository returns fragment entities related to the xpath inputs' - mockFragmentRepository.findByAnchorAndMultipleCpsPaths(_, ['/test/xpath1', '/test/xpath2'] as Set) >> [ - new FragmentEntity(xpath: '/test/xpath1', childFragments: [], anchor: anchorEntity), - new FragmentEntity(xpath: '/test/xpath2', childFragments: [], anchor: anchorEntity)] + mockFragmentRepository.findExtractsWithDescendants(123, ['/test/xpath1', '/test/xpath2'] as Set, _) >> [ + mockFragmentExtract(1, null, 123, '/test/xpath1', null), + mockFragmentExtract(2, null, 123, '/test/xpath2', null) + ] and: 'some data nodes with descendants' def dataNode1 = new DataNode(xpath: '/test/xpath1', leaves: ['id': 'testId1'], childDataNodes: [new DataNode(xpath: '/test/xpath1/child', leaves: ['id': 'childTestId1'])]) def dataNode2 = new DataNode(xpath: '/test/xpath2', leaves: ['id': 'testId2'], childDataNodes: [new DataNode(xpath: '/test/xpath2/child', leaves: ['id': 'childTestId2'])]) @@ -247,26 +252,39 @@ class CpsDataPersistenceServiceSpec extends Specification { def createDataNodesAndMockRepositoryMethodSupportingThem(Map<String, String> xpathToScenarioMap) { def dataNodes = [] - def fragmentEntities = [] + def fragmentExtracts = [] + def fragmentId = 1 xpathToScenarioMap.each { def xpath = it.key def scenario = it.value def dataNode = new DataNodeBuilder().withXpath(xpath).build() dataNodes.add(dataNode) - def fragmentEntity = new FragmentEntity(xpath: xpath, childFragments: []) - fragmentEntities.add(fragmentEntity) - mockFragmentRepository.getByAnchorAndXpath(_, xpath) >> fragmentEntity + def fragmentExtract = mockFragmentExtract(fragmentId, null, null, xpath, null) + fragmentExtracts.add(fragmentExtract) + def fragmentEntity = new FragmentEntity(id: fragmentId, xpath: xpath, childFragments: []) + mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, xpath) >> fragmentEntity if ('EXCEPTION' == scenario) { mockFragmentRepository.save(fragmentEntity) >> { throw new StaleStateException("concurrent updates") } } + fragmentId++ } - mockFragmentRepository.findByAnchorAndMultipleCpsPaths(_, xpathToScenarioMap.keySet()) >> fragmentEntities + mockFragmentRepository.findExtractsWithDescendants(_, xpathToScenarioMap.keySet(), _) >> fragmentExtracts return dataNodes } def mockFragmentWithJson(json) { - def fragmentEntity = new FragmentEntity(xpath: '/parent-01', childFragments: [], attributes: json) - mockFragmentRepository.findByAnchorAndMultipleCpsPaths(123, ['/parent-01'] as Set<String>) >> [fragmentEntity] + def fragmentExtract = mockFragmentExtract(456, null, null, '/parent-01', json) + mockFragmentRepository.findExtractsWithDescendants(123, ['/parent-01'] as Set, _) >> [fragmentExtract] + } + + def mockFragmentExtract(id, parentId, anchorId, xpath, attributes) { + def fragmentExtract = Mock(FragmentExtract) + fragmentExtract.getId() >> id + fragmentExtract.getParentId() >> parentId + fragmentExtract.getAnchorId() >> anchorId + fragmentExtract.getXpath() >> xpath + fragmentExtract.getAttributes() >> attributes + return fragmentExtract } } diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy index 7f4716a7f..98ff211a6 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy @@ -72,8 +72,8 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase { assert countDataNodes(result[0]) == TOTAL_NUMBER_OF_NODES where: 'the following xPaths are used' scenario | xpath || allowedDuration - 'parent' | PERF_TEST_PARENT || 5000 - 'root' | '' || 500 + 'parent' | PERF_TEST_PARENT || 500 + 'root' | '/' || 500 } def 'Query parent data node with many descendants by cps-path'() { @@ -82,8 +82,8 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase { def result = objectUnderTest.queryDataNodes(PERF_DATASPACE, PERF_ANCHOR, '//perf-parent-1' , INCLUDE_ALL_DESCENDANTS) stopWatch.stop() def readDurationInMillis = stopWatch.getTotalTimeMillis() - then: 'read duration is under 500 milliseconds' - recordAndAssertPerformance('Query with many descendants', 500, readDurationInMillis) + then: 'read duration is under 350 milliseconds' + recordAndAssertPerformance('Query with many descendants', 350, readDurationInMillis) and: 'data node is returned with all the descendants populated' assert countDataNodes(result) == TOTAL_NUMBER_OF_NODES } @@ -97,8 +97,8 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase { def readDurationInMillis = stopWatch.getTotalTimeMillis() then: 'the returned number of entities equal to the number of children * number of grandchildren' assert result.size() == xpathsToAllGrandChildren.size() - and: 'it took less then 5000ms' - recordAndAssertPerformance('Find multiple xpaths', 5000, readDurationInMillis) + and: 'it took less then 1000ms' + recordAndAssertPerformance('Find multiple xpaths', 1000, readDurationInMillis) } def 'Query many descendants by cps-path with #scenario'() { @@ -131,8 +131,8 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase { objectUnderTest.updateDataNodesAndDescendants(PERF_DATASPACE, PERF_ANCHOR, dataNodes) stopWatch.stop() def updateDurationInMillis = stopWatch.getTotalTimeMillis() - then: 'update duration is under 900 milliseconds' - recordAndAssertPerformance('Update data nodes with descendants', 900, updateDurationInMillis) + then: 'update duration is under 500 milliseconds' + recordAndAssertPerformance('Update data nodes with descendants', 500, updateDurationInMillis) } def 'Update data nodes without descendants'() { |