aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service
diff options
context:
space:
mode:
authoremaclee <lee.anjella.macabuhay@est.tech>2025-01-12 12:39:55 +0000
committeremaclee <lee.anjella.macabuhay@est.tech>2025-01-16 15:28:15 +0000
commite0ea27a6e0902a4bff75ae5cd4b6025ee0d40a1c (patch)
tree80623f25990b8b2043c7e5690c1f96ba954da8a7 /cps-ncmp-service
parentecfff5cb108e9679ee155a45becaa36a7e9c9059 (diff)
Handle restart case for cps-ncmp gauge metrics
Issue-ID: CPS-2456 Change-Id: I9ac5d6774fcd745d8141551eeff8a1deb1938f57 Signed-off-by: emaclee <lee.anjella.macabuhay@est.tech>
Diffstat (limited to 'cps-ncmp-service')
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java28
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java39
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy36
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy6
7 files changed, 109 insertions, 27 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java
index a29799b13f..fe933d766f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java
@@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class AdminCacheConfig extends HazelcastCacheConfig {
- private static final MapConfig adminCacheMapConfig = createMapConfig("adminCacheMapConfig");
+ private static final MapConfig cmHandleStateCacheMapConfig = createMapConfig("cmHandleStateCacheMapConfig");
/**
* Distributed instance admin cache map for cm handles by state for use of gauge metrics.
@@ -37,13 +37,7 @@ public class AdminCacheConfig extends HazelcastCacheConfig {
*/
@Bean
public IMap<String, Integer> cmHandlesByState() {
- final IMap<String, Integer> cmHandlesByState = getOrCreateHazelcastInstance(adminCacheMapConfig).getMap(
+ return getOrCreateHazelcastInstance(cmHandleStateCacheMapConfig).getMap(
"cmHandlesByState");
- cmHandlesByState.putIfAbsent("advisedCmHandlesCount", 0);
- cmHandlesByState.putIfAbsent("readyCmHandlesCount", 0);
- cmHandlesByState.putIfAbsent("lockedCmHandlesCount", 0);
- cmHandlesByState.putIfAbsent("deletingCmHandlesCount", 0);
- cmHandlesByState.putIfAbsent("deletedCmHandlesCount", 0);
- return cmHandlesByState;
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java
index 31270ca9fc..708508e9d8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java
@@ -25,18 +25,42 @@ import com.hazelcast.map.IMap;
import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.inventory.models.CmHandleState;
import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair;
+import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent;
+import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
+@Slf4j
public class CmHandleStateMonitor {
-
private static final String METRIC_POSTFIX = "CmHandlesCount";
- final IMap<String, Integer> cmHandlesByState;
+
+ private final CmHandleQueryService cmHandleQueryService;
+ private final IMap<String, Integer> cmHandlesByState;
+
+ /**
+ * Method to initialise cm handle state monitor by querying the current state counts
+ * and storing them in the provided map. This method is triggered by NcmpInventoryModelOnboardingFinishedEvent.
+ *
+ * @param ncmpInventoryModelOnboardingFinishedEvent the event that triggers the initialization
+ */
+ @EventListener
+ public void initialiseCmHandleStateMonitor(
+ final NcmpInventoryModelOnboardingFinishedEvent ncmpInventoryModelOnboardingFinishedEvent) {
+ for (final CmHandleState cmHandleState : CmHandleState.values()) {
+ final String cmHandleStateAsString = cmHandleState.name().toLowerCase();
+ final String stateMetricKey = cmHandleStateAsString + METRIC_POSTFIX;
+ final int cmHandleCountForState = cmHandleQueryService.queryCmHandleIdsByState(cmHandleState).size();
+ cmHandlesByState.putIfAbsent(stateMetricKey, cmHandleCountForState);
+ log.info("Cm handle state monitor has set " + stateMetricKey + " to " + cmHandleCountForState);
+ }
+ }
/**
* Asynchronously update the cm handle state metrics.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
index 58a5f553af..514d9b8fe4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
@@ -30,11 +30,15 @@ import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsDataspaceService;
import org.onap.cps.api.CpsModuleService;
import org.onap.cps.init.AbstractModelLoader;
+import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class InventoryModelLoader extends AbstractModelLoader {
+
+ private final ApplicationEventPublisher applicationEventPublisher;
private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2024-02-23.yang";
private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2024-02-23";
private static final String REGISTRY_DATANODE_NAME = "dmi-registry";
@@ -42,14 +46,17 @@ public class InventoryModelLoader extends AbstractModelLoader {
public InventoryModelLoader(final CpsDataspaceService cpsDataspaceService,
final CpsModuleService cpsModuleService,
final CpsAnchorService cpsAnchorService,
- final CpsDataService cpsDataService) {
+ final CpsDataService cpsDataService,
+ final ApplicationEventPublisher applicationEventPublisher) {
super(cpsDataspaceService, cpsModuleService, cpsAnchorService, cpsDataService);
+ this.applicationEventPublisher = applicationEventPublisher;
}
@Override
public void onboardOrUpgradeModel() {
updateInventoryModel();
log.info("Inventory Model updated successfully");
+ applicationEventPublisher.publishEvent(new NcmpInventoryModelOnboardingFinishedEvent(this));
}
private void updateInventoryModel() {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java
new file mode 100644
index 0000000000..92d5e8241d
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java
@@ -0,0 +1,39 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 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.utils.events;
+
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * Custom event triggered when the NCMP inventory model onboarding process is completed.
+ * Extends Spring's {@link ApplicationEvent} to be used within Spring's event-driven architecture.
+ */
+public class NcmpInventoryModelOnboardingFinishedEvent extends ApplicationEvent {
+
+ /**
+ * Creates a new instance of NcmpModelOnboardingFinishedEvent.
+ *
+ * @param source the object that is the source of the event (i.e. the source that completed the onboarding process)
+ */
+ public NcmpInventoryModelOnboardingFinishedEvent(final Object source) {
+ super(source);
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy
index 9b9603369d..a576865262 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy
@@ -45,13 +45,5 @@ class AdminCacheConfigSpec extends Specification {
assert Hazelcast.allHazelcastInstances.size() > 0
and: 'Hazelcast cache instance for cm handle by state is present'
assert Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').getMap('cmHandlesByState') != null
- and: 'the cache already contains 5 entries, an entry for each state'
- def cmHandleByState = Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').getMap('cmHandlesByState')
- assert cmHandleByState.size() == 5
- assert cmHandleByState.containsKey('advisedCmHandlesCount')
- assert cmHandleByState.containsKey('lockedCmHandlesCount')
- assert cmHandleByState.containsKey('readyCmHandlesCount')
- assert cmHandleByState.containsKey('deletingCmHandlesCount')
- assert cmHandleByState.containsKey('deletedCmHandlesCount')
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy
index 9fd40b9605..4d7c22a200 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy
@@ -26,16 +26,19 @@ import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.READY
import com.hazelcast.core.Hazelcast
import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor.DecreasingEntryProcessor
import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor.IncreasingEntryProcessor
+import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent
import spock.lang.Shared
import spock.lang.Specification;
class CmHandleStateMonitorSpec extends Specification {
- def cmHandlesByState = Mock(IMap)
- def objectUnderTest = new CmHandleStateMonitor(cmHandlesByState)
+ def mockCmHandlesByState = Mock(IMap)
+ def mockCmHandleQueryService = Mock(CmHandleQueryService)
+ def objectUnderTest = new CmHandleStateMonitor(mockCmHandleQueryService, mockCmHandlesByState)
@Shared
def entryProcessingMap = Hazelcast.newHazelcastInstance().getMap('entryProcessingMap')
@@ -49,6 +52,25 @@ class CmHandleStateMonitorSpec extends Specification {
Hazelcast.shutdownAll()
}
+ def 'Initialise cm handle state monitor: #scenario'() {
+ given: 'the query service returns a list of cm-handle ids for the given state'
+ mockCmHandleQueryService.queryCmHandleIdsByState(_) >> queryResult
+ and: 'a mocked NcmpModelOnboardingFinishedEvent is triggered'
+ def mockNcmpModelOnboardingFinishedEvent = Mock(NcmpInventoryModelOnboardingFinishedEvent)
+ when: 'the method to initialise cm handle state monitor is triggered by onboarding event'
+ objectUnderTest.initialiseCmHandleStateMonitor(mockNcmpModelOnboardingFinishedEvent)
+ then: 'metrics map is called correct number of times for each state except DELETED, with expected value'
+ 1 * mockCmHandlesByState.putIfAbsent("advisedCmHandlesCount", expectedValue)
+ 1 * mockCmHandlesByState.putIfAbsent("readyCmHandlesCount", expectedValue)
+ 1 * mockCmHandlesByState.putIfAbsent("lockedCmHandlesCount", expectedValue)
+ 1 * mockCmHandlesByState.putIfAbsent("deletingCmHandlesCount", expectedValue)
+ where:
+ scenario | queryResult || expectedValue
+ 'query service returns zero cm handle id'| [] || 0
+ 'query service returns 1 cm handle id' | ['someId'] || 1
+ }
+
+
def 'Update cm handle state metric'() {
given: 'a collection of cm handle state pair'
def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair()
@@ -57,19 +79,19 @@ class CmHandleStateMonitorSpec extends Specification {
when: 'method to update cm handle state metrics is called'
objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair])
then: 'cm handle by state cache map is called once for current and target state for entry processing'
- 1 * cmHandlesByState.executeOnKey('advisedCmHandlesCount', _)
- 1 * cmHandlesByState.executeOnKey('readyCmHandlesCount', _)
+ 1 * mockCmHandlesByState.executeOnKey('advisedCmHandlesCount', _)
+ 1 * mockCmHandlesByState.executeOnKey('readyCmHandlesCount', _)
}
- def 'Updating cm handle state metric with no previous state'() {
+ def 'Update cm handle state metric with no previous state'() {
given: 'a collection of cm handle state pair wherein current state is null'
def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair()
cmHandleTransitionPair.currentYangModelCmHandle = new YangModelCmHandle(compositeState: null)
cmHandleTransitionPair.targetYangModelCmHandle = new YangModelCmHandle(compositeState: new CompositeState(cmHandleState: ADVISED))
- when: 'method to update cm handle state metrics is called'
+ when: 'updating cm handle state metrics'
objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair])
then: 'cm handle by state cache map is called only once'
- 1 * cmHandlesByState.executeOnKey(_, _)
+ 1 * mockCmHandlesByState.executeOnKey(_, _)
}
def 'Applying decreasing entry processor to a key on map where #scenario'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
index ffd1d89fe1..dc6ec4120b 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
@@ -30,6 +30,7 @@ import org.onap.cps.api.CpsModuleService
import org.onap.cps.api.model.Dataspace
import org.slf4j.LoggerFactory
import org.springframework.boot.context.event.ApplicationStartedEvent
+import org.springframework.context.ApplicationEventPublisher
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spock.lang.Specification
@@ -42,7 +43,8 @@ class InventoryModelLoaderSpec extends Specification {
def mockCpsModuleService = Mock(CpsModuleService)
def mockCpsDataService = Mock(CpsDataService)
def mockCpsAnchorService = Mock(CpsAnchorService)
- def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsAnchorService, mockCpsDataService)
+ def mockApplicationEventPublisher = Mock(ApplicationEventPublisher)
+ def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsAnchorService, mockCpsDataService, mockApplicationEventPublisher)
def applicationContext = new AnnotationConfigApplicationContext()
@@ -75,6 +77,8 @@ class InventoryModelLoaderSpec extends Specification {
1 * mockCpsAnchorService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2024-02-23')
and: 'No schema sets are being removed by the module service (yet)'
0 * mockCpsModuleService.deleteSchemaSet(NCMP_DATASPACE_NAME, _, _)
+ and: 'application event publisher is called once'
+ 1 * mockApplicationEventPublisher.publishEvent(_)
}
}