From: Toine Siebelink Date: Wed, 21 Jun 2023 14:44:41 +0000 (+0000) Subject: Merge "Patch # 3: Data operation response event (NCMP → Client App) to comply with... X-Git-Tag: 3.3.3~27 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=aadbac4706a906252083ade06621db38a73fb343;hp=dd4bcaadf2d5b5420669764951ab97eff6ffa4f5;p=cps.git Merge "Patch # 3: Data operation response event (NCMP → Client App) to comply with CloudEvents" --- diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java index 18bdcbeaa..2ae118872 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java @@ -23,7 +23,6 @@ package org.onap.cps.ncmp.api.impl.events.lcm; import java.util.Map; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.inventory.CmHandleState; -import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; /** * The implementation of it should handle the persisting of composite state and delegate the request to publish the @@ -46,13 +45,4 @@ public interface LcmEventsCmHandleStateHandler { */ void updateCmHandleStateBatch(final Map cmHandleStatePerCmHandle); - /** - * Publish LCM Event. - * - * @param targetNcmpServiceCmHandle target NcmpServiceCmHandle - * @param currentNcmpServiceCmHandle current NcmpServiceCmHandle - */ - void publishLcmEventAsynchronously(final NcmpServiceCmHandle targetNcmpServiceCmHandle, - final NcmpServiceCmHandle currentNcmpServiceCmHandle); - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java new file mode 100644 index 000000000..3742719e2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl.events.lcm; + +import java.util.Collection; +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.api.impl.utils.YangDataConverter; +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; +import org.onap.cps.ncmp.events.lcm.v1.LcmEvent; +import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LcmEventsCmHandleStateHandlerAsyncHelper { + + private final LcmEventsCreator lcmEventsCreator; + private final LcmEventsService lcmEventsService; + + /** + * Publish LCM Event in asynchronous manner. + * + * @param targetNcmpServiceCmHandle target NcmpServiceCmHandle + * @param currentNcmpServiceCmHandle current NcmpServiceCmHandle + */ + @Async("notificationExecutor") + public void publishLcmEventAsynchronously(final NcmpServiceCmHandle targetNcmpServiceCmHandle, + final NcmpServiceCmHandle currentNcmpServiceCmHandle) { + publishLcmEvent(targetNcmpServiceCmHandle, currentNcmpServiceCmHandle); + } + + /** + * Publish LcmEvent in batches and in asynchronous manner. + * + * @param cmHandleTransitionPairs Pair of existing and modified cm handle represented as YangModelCmHandle + */ + @Async("notificationExecutor") + public void publishLcmEventBatchAsynchronously( + final Collection cmHandleTransitionPairs) { + cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> publishLcmEvent( + toNcmpServiceCmHandle(cmHandleTransitionPair.getTargetYangModelCmHandle()), + toNcmpServiceCmHandle(cmHandleTransitionPair.getCurrentYangModelCmHandle()))); + } + + private void publishLcmEvent(final NcmpServiceCmHandle targetNcmpServiceCmHandle, + final NcmpServiceCmHandle existingNcmpServiceCmHandle) { + final String cmHandleId = targetNcmpServiceCmHandle.getCmHandleId(); + final LcmEventHeader lcmEventHeader = + lcmEventsCreator.populateLcmEventHeader(cmHandleId, targetNcmpServiceCmHandle, + existingNcmpServiceCmHandle); + final LcmEvent lcmEvent = + lcmEventsCreator.populateLcmEvent(cmHandleId, targetNcmpServiceCmHandle, existingNcmpServiceCmHandle); + lcmEventsService.publishLcmEvent(cmHandleId, lcmEvent, lcmEventHeader); + } + + private static NcmpServiceCmHandle toNcmpServiceCmHandle(final YangModelCmHandle yangModelCmHandle) { + return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelCmHandle); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java index f42cd39d4..2f77ec320 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java @@ -43,9 +43,6 @@ import org.onap.cps.ncmp.api.inventory.CompositeState; import org.onap.cps.ncmp.api.inventory.CompositeStateUtils; import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle; -import org.onap.cps.ncmp.events.lcm.v1.LcmEvent; -import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Slf4j @@ -54,8 +51,7 @@ import org.springframework.stereotype.Service; public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleStateHandler { private final InventoryPersistence inventoryPersistence; - private final LcmEventsCreator lcmEventsCreator; - private final LcmEventsService lcmEventsService; + private final LcmEventsCmHandleStateHandlerAsyncHelper lcmEventsCmHandleStateHandlerAsyncHelper; @Override public void updateCmHandleState(final YangModelCmHandle updatedYangModelCmHandle, @@ -70,7 +66,8 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState final YangModelCmHandle currentYangModelCmHandle = YangModelCmHandle.deepCopyOf(updatedYangModelCmHandle); updateToSpecifiedCmHandleState(updatedYangModelCmHandle, targetCmHandleState); persistCmHandle(updatedYangModelCmHandle, currentYangModelCmHandle); - publishLcmEventAsynchronously(toNcmpServiceCmHandle(updatedYangModelCmHandle), + lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventAsynchronously( + toNcmpServiceCmHandle(updatedYangModelCmHandle), toNcmpServiceCmHandle(currentYangModelCmHandle)); } } @@ -82,37 +79,7 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState final Collection cmHandleTransitionPairs = prepareCmHandleTransitionBatch(cmHandleStatePerCmHandle); persistCmHandleBatch(cmHandleTransitionPairs); - publishLcmEventBatchAsynchronously(cmHandleTransitionPairs); - } - - @Async("notificationExecutor") - @Override - public void publishLcmEventAsynchronously(final NcmpServiceCmHandle targetNcmpServiceCmHandle, - final NcmpServiceCmHandle currentNcmpServiceCmHandle) { - publishLcmEvent(targetNcmpServiceCmHandle, currentNcmpServiceCmHandle); - } - - /** - * Publish LcmEvent in batches and in asynchronous manner. - * - * @param cmHandleTransitionPairs Pair of existing and modified cm handle represented as YangModelCmHandle - */ - @Async("notificationExecutor") - public void publishLcmEventBatchAsynchronously(final Collection cmHandleTransitionPairs) { - cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> publishLcmEvent( - toNcmpServiceCmHandle(cmHandleTransitionPair.getTargetYangModelCmHandle()), - toNcmpServiceCmHandle(cmHandleTransitionPair.getCurrentYangModelCmHandle()))); - } - - private void publishLcmEvent(final NcmpServiceCmHandle targetNcmpServiceCmHandle, - final NcmpServiceCmHandle existingNcmpServiceCmHandle) { - final String cmHandleId = targetNcmpServiceCmHandle.getCmHandleId(); - final LcmEventHeader lcmEventHeader = - lcmEventsCreator.populateLcmEventHeader(cmHandleId, targetNcmpServiceCmHandle, - existingNcmpServiceCmHandle); - final LcmEvent lcmEvent = - lcmEventsCreator.populateLcmEvent(cmHandleId, targetNcmpServiceCmHandle, existingNcmpServiceCmHandle); - lcmEventsService.publishLcmEvent(cmHandleId, lcmEvent, lcmEventHeader); + lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventBatchAsynchronously(cmHandleTransitionPairs); } private Collection prepareCmHandleTransitionBatch( diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy index e449d65ac..bfebc44ba 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy @@ -39,7 +39,8 @@ class LcmEventsCmHandleStateHandlerImplSpec extends Specification { def mockLcmEventsCreator = Mock(LcmEventsCreator) def mockLcmEventsService = Mock(LcmEventsService) - def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, mockLcmEventsCreator, mockLcmEventsService) + def lcmEventsCmHandleStateHandlerAsyncHelper = new LcmEventsCmHandleStateHandlerAsyncHelper(mockLcmEventsCreator, mockLcmEventsService) + def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, lcmEventsCmHandleStateHandlerAsyncHelper) def cmHandleId = 'cmhandle-id-1' def compositeState diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy index a02d21c41..b3c884127 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy @@ -27,6 +27,7 @@ import org.onap.cps.integration.performance.base.CpsPerfTestBase class UpdatePerfTest extends CpsPerfTestBase { CpsDataService objectUnderTest + def now = OffsetDateTime.now() def setup() { objectUnderTest = cpsDataService } @@ -36,7 +37,7 @@ class UpdatePerfTest extends CpsPerfTestBase { def jsonData = readResourceDataFile('openroadm/innerNode.json').replace('NODE_ID_HERE', '10') when: 'the fragment entities are updated by the data nodes' stopWatch.start() - objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', parentNodeXpath, jsonData, OffsetDateTime.now()) + objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', parentNodeXpath, jsonData, now) stopWatch.stop() def updateDurationInMillis = stopWatch.getTotalTimeMillis() then: 'update duration is under 1000 milliseconds' @@ -52,11 +53,39 @@ class UpdatePerfTest extends CpsPerfTestBase { ]} when: 'the fragment entities are updated by the data nodes' stopWatch.start() - objectUnderTest.updateDataNodesAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm2', nodesJsonData, OffsetDateTime.now()) + objectUnderTest.updateDataNodesAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm2', nodesJsonData, now) stopWatch.stop() def updateDurationInMillis = stopWatch.getTotalTimeMillis() then: 'update duration is under 5000 milliseconds' recordAndAssertPerformance('Update 10 data nodes', 4000, updateDurationInMillis) } + def 'Update leaves for 1 data node'() { + given: 'Updated json for openroadm data' + def jsonDataUpdated = "{'openroadm-device':{'device-id':'C201-7-1A-10','status':'fail','ne-state':'jeopardy'}}" + def jsonDataOriginal = "{'openroadm-device':{'device-id':'C201-7-1A-10','status':'success','ne-state':'inservice'}}" + when: 'update is performed for leaves' + stopWatch.start() + objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm3', "/openroadm-devices", jsonDataUpdated, now) + objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm3', "/openroadm-devices", jsonDataOriginal, now) + stopWatch.stop() + def updateDurationInMillis = stopWatch.getTotalTimeMillis() + then: 'update duration is under 750 milliseconds' + recordAndAssertPerformance('Update leaves for 1 data node', 750, updateDurationInMillis) + } + + def 'Batch update leaves for 50 data nodes'() { + given: 'Updated json for openroadm data' + def jsonDataUpdated = "{'openroadm-device':[" + (1..50).collect { "{'device-id':'C201-7-1A-" + it + "','status':'fail','ne-state':'jeopardy'}" }.join(",") + "]}" + def jsonDataOriginal = "{'openroadm-device':[" + (1..50).collect { "{'device-id':'C201-7-1A-" + it + "','status':'success','ne-state':'inservice'}" }.join(",") + "]}" + when: 'update is performed for leaves' + stopWatch.start() + objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm4', "/openroadm-devices", jsonDataUpdated, now) + objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm4', "/openroadm-devices", jsonDataOriginal, now) + stopWatch.stop() + def updateDurationInMillis = stopWatch.getTotalTimeMillis() + then: 'update duration is under 3500 milliseconds' + recordAndAssertPerformance('Batch update leaves for 50 data nodes', 3500, updateDurationInMillis) + } + }