From b5178cc5f3261c62714537975f57d04b18b90fd4 Mon Sep 17 00:00:00 2001 From: Paul Chandler Date: Wed, 11 Sep 2024 14:45:56 +0100 Subject: [PATCH] 674 Specify Interval for Next Connection (#712) * 674 Specify Interval for Next Connection --------- Co-authored-by: Paul Chandler --- CHANGES.md | 1 + .../application/config/Interval.java | 67 +++++++++++++++++++ .../connection/AgentConnectionConfig.java | 1 + .../config/connection/ConnectionConfig.java | 24 +++++++ .../application/spring/BeanConfigurator.java | 10 ++- application/src/main/resources/ecc.yml | 7 ++ .../application/config/TestConfig.java | 9 +++ .../application/config/TestDefaultConfig.java | 60 +++++++++++++++++ application/src/test/resources/all_set.yml | 3 + .../src/test/resources/nothing_set.yml | 2 +- .../ecchronos/data/sync/EccNodesSync.java | 37 +++++++++- .../ecchronos/data/sync/TestEccNodesSync.java | 3 + 12 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/Interval.java create mode 100644 application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java diff --git a/CHANGES.md b/CHANGES.md index 16a8b9e40..4c96673d4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Version 1.0.0 (Not yet Release) +* Specify Interval for Next Connection - Issue #674 * Retry Policy for Jmx Connection - Issue #700 * Update Architecture and Tests Documentations to Add the Agent Features and The cassandra-test-image - Issue #707 * Enhance Test Infrastructure by Adding Cassandra-Test-Image Module With Multi-Datacenter Cluster and Abstract Integration Test Class - Issue #706 diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/Interval.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/Interval.java new file mode 100644 index 000000000..dfb5b660a --- /dev/null +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/Interval.java @@ -0,0 +1,67 @@ +/* + * Copyright 2024 Telefonaktiebolaget LM Ericsson + * + * 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. + */ +package com.ericsson.bss.cassandra.ecchronos.application.config; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +public class Interval +{ + static final int DEFAULT_TIME_IN_MINUTES = 60; + private long myTime = DEFAULT_TIME_IN_MINUTES; + private TimeUnit myUnit = TimeUnit.MINUTES; + + public Interval() + { + // Default constructor for jackson + } + + public Interval(final long time, final TimeUnit timeUnit) + { + myTime = time; + myUnit = timeUnit; + } + + public final long getInterval(final TimeUnit timeUnit) + { + return timeUnit.convert(myTime, myUnit); + } + + @JsonProperty("time") + public final long getTime() + { + return myTime; + } + + @JsonProperty("time") + public final void setTime(final long time) + { + myTime = time; + } + + @JsonProperty("unit") + public final TimeUnit getUnit() + { + return myUnit; + } + + @JsonProperty("unit") + public final void setUnit(final String unit) + { + myUnit = TimeUnit.valueOf(unit.toUpperCase(Locale.US)); + } +} diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/AgentConnectionConfig.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/AgentConnectionConfig.java index 2177ca5cd..07a37a542 100644 --- a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/AgentConnectionConfig.java +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/AgentConnectionConfig.java @@ -105,6 +105,7 @@ public String getLocalDatacenter() return myLocalDatacenter; } + /** * Gets the DataCenterAwarePolicy used for load-balancing policy. * diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/ConnectionConfig.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/ConnectionConfig.java index 7ad8de2e1..1de923756 100644 --- a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/ConnectionConfig.java +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/ConnectionConfig.java @@ -14,12 +14,14 @@ */ package com.ericsson.bss.cassandra.ecchronos.application.config.connection; +import com.ericsson.bss.cassandra.ecchronos.application.config.Interval; import com.fasterxml.jackson.annotation.JsonProperty; public class ConnectionConfig { private DistributedNativeConnection myCqlConnection = new DistributedNativeConnection(); private DistributedJmxConnection myJmxConnection = new DistributedJmxConnection(); + private Interval myConnectionDelay = new Interval(); @JsonProperty("cql") public final DistributedNativeConnection getCqlConnection() @@ -56,4 +58,26 @@ public final String toString() { return String.format("Connection(cql=%s, jmx=%s)", myCqlConnection, myJmxConnection); } + /** + * Sets the connectionDelay used to specify the time until the next connection. + * + * @param connectionDelay + * the local datacenter to set. + */ + @JsonProperty("connectionDelay") + public void setConnectionDelay(final Interval connectionDelay) + { + myConnectionDelay = connectionDelay; + } + /** + * Gets the connectionDelay used to specify the time until the next connection. + * + * @return the connectionDelay. + */ + @JsonProperty("connectionDelay") + public Interval getConnectionDelay() + { + return myConnectionDelay; + } + } diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java index d0a8ef5d5..30f582e0a 100644 --- a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java @@ -14,6 +14,7 @@ */ package com.ericsson.bss.cassandra.ecchronos.application.spring; +import com.ericsson.bss.cassandra.ecchronos.application.config.Interval; import com.ericsson.bss.cassandra.ecchronos.application.config.security.CqlTLSConfig; import com.ericsson.bss.cassandra.ecchronos.application.config.security.ReloadingCertificateHandler; import com.ericsson.bss.cassandra.ecchronos.application.providers.AgentJmxConnectionProvider; @@ -178,11 +179,13 @@ public DistributedNativeConnectionProvider distributedNativeConnectionProvider( * if the local host name cannot be determined. * @throws EcChronosException * if there is an error during node synchronization. + * @throws ConfigurationException + * if there is an error during node synchronization. */ @Bean public EccNodesSync eccNodesSync( final DistributedNativeConnectionProvider distributedNativeConnectionProvider - ) throws UnknownHostException, EcChronosException + ) throws UnknownHostException, EcChronosException, ConfigurationException { return getEccNodesSync(distributedNativeConnectionProvider); } @@ -273,12 +276,15 @@ private static CertificateHandler createCertificateHandler( private EccNodesSync getEccNodesSync( final DistributedNativeConnectionProvider distributedNativeConnectionProvider - ) throws UnknownHostException, EcChronosException + ) throws UnknownHostException, EcChronosException, ConfigurationException { + Interval connectionDelay = config().getConnectionConfig().getConnectionDelay(); EccNodesSync myEccNodesSync = EccNodesSync.newBuilder() .withInitialNodesList(distributedNativeConnectionProvider.getNodes()) .withSession(distributedNativeConnectionProvider.getCqlSession()) .withEcchronosID(ecChronosID) + .withConnectionDelayValue(connectionDelay.getTime()) + .withConnectionDelayUnit(connectionDelay.getUnit()) .build(); myEccNodesSync.acquireNodes(); LOG.info("Nodes acquired with success"); diff --git a/application/src/main/resources/ecc.yml b/application/src/main/resources/ecc.yml index b6f0c2673..835b266af 100644 --- a/application/src/main/resources/ecc.yml +++ b/application/src/main/resources/ecc.yml @@ -87,6 +87,13 @@ connection: ## Extending this allows to manipulate the SSLEngine and SSLParameters. ## certificateHandler: com.ericsson.bss.cassandra.ecchronos.application.config.security.ReloadingCertificateHandler + ## + ## Specify the interval until the next connection to a node + ## Unit can be SECONDS, MINUTES, HOURS, DAYS + ## + connectionDelay: + time: 45 + unit: MINUTES jmx: ## ## The class used to provide JMX connections to Apache Cassandra. diff --git a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java index c1a88fa21..ce05356e1 100644 --- a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java +++ b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java @@ -30,6 +30,7 @@ import java.io.File; import java.io.IOException; +import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; @@ -236,4 +237,12 @@ public void testMaxDelayLessThanStartDelayThrowsException() }); assertEquals("Max delay cannot be less than start delay.", exception.getMessage()); } + public void testConnectionDelay() + { + Interval connectionDelay = config.getConnectionConfig().getConnectionDelay(); + assertThat(connectionDelay.getUnit()).isEqualTo(TimeUnit.MINUTES); + assertThat(connectionDelay.getTime()).isEqualTo(45l); + } + } + diff --git a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java new file mode 100644 index 000000000..686aba387 --- /dev/null +++ b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java @@ -0,0 +1,60 @@ +/* + * Copyright 2024 Telefonaktiebolaget LM Ericsson + * + * 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. + */ +package com.ericsson.bss.cassandra.ecchronos.application.config; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class TestDefaultConfig +{ + private static final String DEFAULT_AGENT_FILE_NAME = "nothing_set.yml"; + private static Config config; + + + @Before + public void setup() throws StreamReadException, DatabindException, IOException + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + File file = new File(classLoader.getResource(DEFAULT_AGENT_FILE_NAME).getFile()); + + ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); + + config = objectMapper.readValue(file, Config.class); + + } + + + + @Test + public void testConnectionDelayDefault() + { + Interval connectionDelay = config.getConnectionConfig().getConnectionDelay(); + assertThat(connectionDelay.getUnit()).isEqualTo(TimeUnit.MINUTES); + assertThat(connectionDelay.getTime()).isEqualTo(60l); + } + +} \ No newline at end of file diff --git a/application/src/test/resources/all_set.yml b/application/src/test/resources/all_set.yml index 53917e31a..6ae06ec29 100644 --- a/application/src/test/resources/all_set.yml +++ b/application/src/test/resources/all_set.yml @@ -42,6 +42,9 @@ connection: - host: 127.0.0.4 port: 9042 provider: com.ericsson.bss.cassandra.ecchronos.application.providers.AgentNativeConnectionProvider + connectionDelay: + time: 45 + unit: minutes jmx: provider: com.ericsson.bss.cassandra.ecchronos.application.providers.AgentJmxConnectionProvider retryPolicy: diff --git a/application/src/test/resources/nothing_set.yml b/application/src/test/resources/nothing_set.yml index 65767b5b8..b6a7610f0 100644 --- a/application/src/test/resources/nothing_set.yml +++ b/application/src/test/resources/nothing_set.yml @@ -26,4 +26,4 @@ connection: retrySchedule: initialDelay: fixedDelay: - unit: \ No newline at end of file + unit: diff --git a/data/src/main/java/com/ericsson/bss/cassandra/ecchronos/data/sync/EccNodesSync.java b/data/src/main/java/com/ericsson/bss/cassandra/ecchronos/data/sync/EccNodesSync.java index 389b3ed71..5b8025c37 100644 --- a/data/src/main/java/com/ericsson/bss/cassandra/ecchronos/data/sync/EccNodesSync.java +++ b/data/src/main/java/com/ericsson/bss/cassandra/ecchronos/data/sync/EccNodesSync.java @@ -30,7 +30,9 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.Locale; import java.util.UUID; +import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,6 +69,8 @@ public final class EccNodesSync private final PreparedStatement myCreateStatement; private final PreparedStatement myUpdateStatusStatement; private final PreparedStatement mySelectStatusStatement; + private final Long connectionDelayValue; + private final ChronoUnit connectionDelayUnit; private EccNodesSync(final Builder builder) throws UnknownHostException { @@ -97,6 +101,9 @@ private EccNodesSync(final Builder builder) throws UnknownHostException .whereColumn(COLUMN_ECCHRONOS_ID).isEqualTo(bindMarker()) .build()); ecChronosID = builder.myEcchronosID; + + connectionDelayValue = builder.myConnectionDelayValue; + connectionDelayUnit = builder.myConnectionDelayUnit; } public ResultSet getResultSet() @@ -138,7 +145,7 @@ private ResultSet acquireNode(final Node node) node.getEndPoint().toString(), node.getState().toString(), Instant.now(), - Instant.now().plus(DEFAULT_CONNECTION_DELAY_IN_MINUTES, ChronoUnit.MINUTES), + Instant.now().plus(connectionDelayValue, connectionDelayUnit), node.getHostId()); } @@ -232,6 +239,8 @@ public static class Builder private CqlSession mySession; private List initialNodesList; private String myEcchronosID; + private Long myConnectionDelayValue; + private ChronoUnit myConnectionDelayUnit; /** * Builds EccNodesSync with session. @@ -259,6 +268,32 @@ public Builder withInitialNodesList(final List nodes) return this; } + /** + * Builds EccNodesSync with Connection Delay. + * + * @param connectionDelayValue + * delay before connecting, in the unit specified in withConnectionDelayUnit + * @return Builder + */ + public Builder withConnectionDelayValue(final Long connectionDelayValue) + { + this.myConnectionDelayValue = connectionDelayValue; + return this; + } + + /** + * Builds EccNodesSync with Connection Delay Unit. + * + * @param connectionDelayUnit + * Unit of the delay before connecting + * @return Builder + */ + public Builder withConnectionDelayUnit(final TimeUnit connectionDelayUnit) + { + this.myConnectionDelayUnit = ChronoUnit.valueOf(connectionDelayUnit.toString().toUpperCase(Locale.US)); + return this; + } + /** * Builds EccNodesSync with ecchronosID. * diff --git a/data/src/test/java/com/ericsson/bss/cassandra/ecchronos/data/sync/TestEccNodesSync.java b/data/src/test/java/com/ericsson/bss/cassandra/ecchronos/data/sync/TestEccNodesSync.java index 865cb387d..3fa826689 100644 --- a/data/src/test/java/com/ericsson/bss/cassandra/ecchronos/data/sync/TestEccNodesSync.java +++ b/data/src/test/java/com/ericsson/bss/cassandra/ecchronos/data/sync/TestEccNodesSync.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; +import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; @@ -72,6 +73,8 @@ public void setup() throws IOException eccNodesSync = EccNodesSync.newBuilder() .withSession(mySession) .withInitialNodesList(nodesList) + .withConnectionDelayValue(Long.valueOf(10)) + .withConnectionDelayUnit(TimeUnit.MINUTES) .withEcchronosID("ecchronos-test").build(); }