PAP should discard old PDP messages 39/109239/3
authorJim Hahn <jrh3@att.com>
Tue, 16 Jun 2020 21:52:17 +0000 (17:52 -0400)
committerJim Hahn <jrh3@att.com>
Wed, 17 Jun 2020 18:41:01 +0000 (14:41 -0400)
Modified PAP to discard any messages old than 10 minutes so that
if PAP is unable to communicate with DMaaP and then suddently gets
flooded, it will discard old messages.
Updates per review comments
- made the "max message age" configurable, with a default of 10 minutes

Issue-ID: POLICY-2170
Change-Id: I541c03aabf29482af12a07f51eeb5888bbafbf31
Signed-off-by: Jim Hahn <jrh3@att.com>
main/src/main/java/org/onap/policy/pap/main/comm/PdpHeartbeatListener.java
main/src/main/java/org/onap/policy/pap/main/comm/PdpStatusMessageHandler.java
main/src/main/java/org/onap/policy/pap/main/parameters/PdpParameters.java
main/src/main/java/org/onap/policy/pap/main/startstop/PapActivator.java
main/src/test/java/org/onap/policy/pap/main/comm/PdpHeartbeatListenerTest.java
main/src/test/java/org/onap/policy/pap/main/parameters/TestPdpParameters.java
main/src/test/resources/parameters/PapConfigParametersStd.json

index fc61c1a..512609a 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +24,7 @@ package org.onap.policy.pap.main.comm;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.listeners.TypedMessageListener;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.pap.main.parameters.PdpParameters;
 
 /**
  * Listener for PDP Status messages which either represent registration or heart beat.
@@ -31,10 +33,21 @@ import org.onap.policy.models.pdp.concepts.PdpStatus;
  */
 public class PdpHeartbeatListener implements TypedMessageListener<PdpStatus> {
 
+    private final PdpParameters params;
+
+    /**
+     * Constructs the object.
+     *
+     * @param params PDP parameters
+     */
+    public PdpHeartbeatListener(PdpParameters params) {
+        this.params = params;
+    }
+
     @Override
     public void onTopicEvent(final CommInfrastructure infra, final String topic, final PdpStatus message) {
 
-        final PdpStatusMessageHandler handler = new PdpStatusMessageHandler();
+        final PdpStatusMessageHandler handler = new PdpStatusMessageHandler(params);
         handler.handlePdpStatus(message);
     }
 }
index cf73a13..674a07f 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019-2020 Nordix Foundation.
- *  Modifications Copyright (C) 2019 AT&T Intellectual Property.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ package org.onap.policy.pap.main.comm;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
-
+import java.util.concurrent.TimeUnit;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.onap.policy.common.utils.services.Registry;
 import org.onap.policy.models.base.PfModelException;
@@ -40,6 +40,7 @@ import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.provider.PolicyModelsProvider;
 import org.onap.policy.pap.main.PapConstants;
 import org.onap.policy.pap.main.PolicyPapException;
+import org.onap.policy.pap.main.parameters.PdpParameters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,11 +53,16 @@ import org.slf4j.LoggerFactory;
 public class PdpStatusMessageHandler extends PdpMessageGenerator {
     private static final Logger LOGGER = LoggerFactory.getLogger(PdpStatusMessageHandler.class);
 
+    private final PdpParameters params;
+
     /**
      * Constructs the object.
+     *
+     * @param params PDP parameters
      */
-    public PdpStatusMessageHandler() {
+    public PdpStatusMessageHandler(PdpParameters params) {
         super(true);
+        this.params = params;
     }
 
     /**
@@ -65,6 +71,13 @@ public class PdpStatusMessageHandler extends PdpMessageGenerator {
      * @param message the PdpStatus message
      */
     public void handlePdpStatus(final PdpStatus message) {
+        long diffms = System.currentTimeMillis() - message.getTimestampMs();
+        if (diffms > params.getMaxMessageAgeMs()) {
+            long diffsec = TimeUnit.SECONDS.convert(diffms, TimeUnit.MILLISECONDS);
+            LOGGER.info("discarding status message from {} age {}s", message.getName(), diffsec);
+            return;
+        }
+
         synchronized (updateLock) {
             try (PolicyModelsProvider databaseProvider = modelProviderWrapper.create()) {
                 if (message.getPdpSubgroup() == null) {
index 1776772..72b11d7 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP PAP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
 
 package org.onap.policy.pap.main.parameters;
 
+import java.util.concurrent.TimeUnit;
 import lombok.Getter;
 import org.onap.policy.common.parameters.ParameterGroupImpl;
 import org.onap.policy.common.parameters.annotations.Min;
@@ -34,9 +35,19 @@ import org.onap.policy.common.parameters.annotations.NotNull;
 @Getter
 public class PdpParameters extends ParameterGroupImpl {
 
+    /**
+     * Default maximum message age, in milliseconds, that should be examined. Any message
+     * older than this is discarded.
+     */
+    public static final long DEFAULT_MAX_AGE_MS = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES);
+
+
     @Min(1)
     private long heartBeatMs;
 
+    @Min(1)
+    private long maxMessageAgeMs =  DEFAULT_MAX_AGE_MS;
+
     private PdpUpdateParameters updateParameters;
     private PdpStateChangeParameters stateChangeParameters;
 
index 83b9151..fd13c23 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Nordix Foundation.
- *  Modifications Copyright (C) 2019 AT&T Intellectual Property.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -109,7 +109,7 @@ public class PapActivator extends ServiceManagerContainer {
             this.papParameterGroup = papParameterGroup;
             this.msgDispatcher = new MessageTypeDispatcher(MSG_TYPE_NAMES);
             this.reqIdDispatcher = new RequestIdDispatcher<>(PdpStatus.class, REQ_ID_NAMES);
-            this.pdpHeartbeatListener = new PdpHeartbeatListener();
+            this.pdpHeartbeatListener = new PdpHeartbeatListener(papParameterGroup.getPdpParameters());
 
         } catch (final RuntimeException e) {
             throw new PolicyPapRuntimeException(e);
index 7dd7eef..1439660 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019-2020 Nordix Foundation.
+ *  Modifications Copyright (C) 2020 AT&T Intellectual Property.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,7 +28,6 @@ import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
-
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.utils.coder.CoderException;
@@ -39,6 +39,7 @@ import org.onap.policy.models.pdp.concepts.PdpSubGroup;
 import org.onap.policy.models.pdp.enums.PdpHealthStatus;
 import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.pap.main.parameters.PdpParameters;
 import org.onap.policy.pap.main.rest.e2e.End2EndBase;
 
 /**
@@ -62,7 +63,7 @@ public class PdpHeartbeatListenerTest extends End2EndBase {
     @Test
     public void testPdpHeartbeatListener() throws CoderException, PfModelException {
         addGroups("PdpGroups.json");
-        pdpHeartbeatListener = new PdpHeartbeatListener();
+        pdpHeartbeatListener = new PdpHeartbeatListener(new PdpParameters());
 
         // Testing pdp registration success case
         final PdpStatus status1 = new PdpStatus();
@@ -158,6 +159,21 @@ public class PdpHeartbeatListenerTest extends End2EndBase {
         pdpHeartbeatListener.onTopicEvent(INFRA, TOPIC, status7);
         verifyPdpGroup(DEFAULT_GROUP, 2);
 
+        // Testing old message for pdp_1 - should have no effect
+        final PdpStatus status7b = new PdpStatus();
+        status7b.setTimestampMs(System.currentTimeMillis() - PdpParameters.DEFAULT_MAX_AGE_MS - 1);
+        status7b.setName(PDP_NAME);
+        status7b.setState(PdpState.TERMINATED);
+        status7b.setPdpGroup(DEFAULT_GROUP);
+        status7b.setPdpType(APEX_TYPE);
+        status7b.setPdpSubgroup(APEX_TYPE);
+        status7b.setHealthy(PdpHealthStatus.HEALTHY);
+        final List<ToscaPolicyIdentifier> idents7b =
+                Arrays.asList(new ToscaPolicyIdentifier(POLICY_NAME, POLICY_VERSION));
+        status7b.setPolicies(idents7b);
+        pdpHeartbeatListener.onTopicEvent(INFRA, TOPIC, status7b);
+        verifyPdpGroup(DEFAULT_GROUP, 2);
+
         // Testing pdp termination case for pdp_1
         final PdpStatus status8 = new PdpStatus();
         status8.setName(PDP_NAME);
@@ -190,7 +206,7 @@ public class PdpHeartbeatListenerTest extends End2EndBase {
     @Test
     public void testPdpStatistics() throws CoderException, PfModelException, ParseException {
         addGroups("PdpGroups.json");
-        pdpHeartbeatListener = new PdpHeartbeatListener();
+        pdpHeartbeatListener = new PdpHeartbeatListener(new PdpParameters());
         timeStamp = new SimpleDateFormat("yyyy-MM-dd").parse("2020-01-01");
 
         // init default pdp group
index 1474bbf..c47b530 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP PAP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -48,6 +48,11 @@ public class TestPdpParameters {
         assertEquals(5, state.getMaxWaitMs());
 
         assertEquals(6L, params.getHeartBeatMs());
+
+        assertEquals(20000L, params.getMaxMessageAgeMs());
+
+        // check default value
+        assertEquals(600000L, new PdpParameters().getMaxMessageAgeMs());
     }
 
     @Test
@@ -67,6 +72,13 @@ public class TestPdpParameters {
         assertTrue(result.getResult().contains(
                         "field 'heartBeatMs' type 'long' value '0' INVALID, must be >= 1".replace('\'', '"')));
 
+        // invalid max message age
+        json2 = json.replaceFirst(": 20000", ": 0");
+        result = coder.decode(json2, PapParameterGroup.class).getPdpParameters().validate();
+        assertFalse(result.isValid());
+        assertTrue(result.getResult().contains(
+                        "field 'maxMessageAgeMs' type 'long' value '0' INVALID, must be >= 1".replace('\'', '"')));
+
         // no update params
         json2 = testData.nullifyField(json, "updateParameters");
         result = coder.decode(json2, PapParameterGroup.class).getPdpParameters().validate();
index 47925df..a11782b 100644 (file)
@@ -16,7 +16,8 @@
             "maxRetryCount": 1,
             "maxWaitMs": 5
         },
-        "heartBeatMs": 6
+        "heartBeatMs": 6,
+        "maxMessageAgeMs": 20000
     },
     "databaseProviderParameters": {
         "name": "PolicyModelsProviderParameters",