Simplify hostname-based startup delay logic with consistent hash-based approach 11/140711/1
authorsourabh_sourabh <sourabh.sourabh@est.tech>
Thu, 17 Apr 2025 16:38:54 +0000 (17:38 +0100)
committersourabh_sourabh <sourabh.sourabh@est.tech>
Thu, 17 Apr 2025 16:38:54 +0000 (17:38 +0100)
- Removed conditional logic based on last character of the hostname

- Applied a uniform hash-based delay calculation up to 5000 ms

- Improves consistency and simplifies the code logic

- Updated JavaDoc to reflect the new approach

Issue-ID: CPS-2752
Change-Id: Ic9e5cffb7396695e90b94edba79984f7f0f859aa
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
cps-application/src/main/java/org/onap/cps/startup/InstanceStartupDelayManager.java
cps-application/src/test/groovy/org/onap/cps/startup/InstanceStartupDelayManagerSpec.groovy

index b221bdc..927c59f 100644 (file)
@@ -29,25 +29,20 @@ import lombok.extern.slf4j.Slf4j;
 public class InstanceStartupDelayManager {
 
     /**
-     * Applies a startup delay based on the host's name to avoid race conditions during schema migration.
-
-     * In environments with multiple instances (e.g., Docker Compose, Kubernetes),
-     * this delay helps avoid simultaneous Liquibase executions that may result in conflicts.
-
+     * Applies a consistent hash-based startup delay based on the host's name
+     * to avoid race conditions during schema migration.
+     * This method is useful in environments with multiple instances
+     * (e.g., Docker Compose, Kubernetes), where simultaneous Liquibase executions
+     * might result in conflicts.
      * Delay logic:
-     * - If the last character of the hostname is a digit, delay = digit * 1000 ms.
-     * - Otherwise, a hash-based fallback delay up to 3000 ms is applied.
+     * - A hash of the hostname is calculated.
+     * - The result is used to derive a delay up to 5000 milliseconds.
+     * - This provides a reasonably distributed delay across instances.
      */
     public void applyHostnameBasedStartupDelay() {
         try {
             final String hostname = getHostName();
-            final char lastCharacterOfHostName = hostname.charAt(hostname.length() - 1);
-            final long startupDelayInMillis;
-            if (Character.isDigit(lastCharacterOfHostName)) {
-                startupDelayInMillis = Character.getNumericValue(lastCharacterOfHostName) * 1_000L;
-            } else {
-                startupDelayInMillis = Math.abs(hostname.hashCode() % 3_000L);
-            }
+            final long startupDelayInMillis = Math.abs(hostname.hashCode() % 5_000L);
             log.info("Startup delay applied for Hostname: {} | Delay: {} ms", hostname, startupDelayInMillis);
             haveALittleSleepInMs(startupDelayInMillis);
         } catch (final InterruptedException e) {
index 68ef6cc..0ad02f4 100644 (file)
@@ -27,34 +27,14 @@ class InstanceStartupDelayManagerSpec extends Specification {
     def objectUnderTest = Spy(InstanceStartupDelayManager)
 
     def 'Startup delay with real hostname.'() {
-        when: 'start up delay is called'
-            objectUnderTest.applyHostnameBasedStartupDelay()
-        then: 'the system will sleep for some time'
-            1 * objectUnderTest.haveALittleSleepInMs(_ as Long) >> { /* don't really sleep */ }
-    }
-
-    def 'Startup delay for hostname that ends with digit.'() {
-        given: 'a hostname with a digit at the end'
-            objectUnderTest.getHostName() >> 'host' + lastDigit
-        and: 'the expected delay is based on last digit'
-            def expectedDelay = lastDigit * 1_000
-        when: 'startup delay is called'
-            objectUnderTest.applyHostnameBasedStartupDelay()
-        then: 'the system will sleep for expected time'
-            1 * objectUnderTest.haveALittleSleepInMs(expectedDelay)
-        where: 'following last digits are used'
-            lastDigit << [0, 1]
-    }
-
-    def 'Startup delay for hostname that does not end with digit.'() {
-        given: 'a hostname with a non-digit at the end'
+        given: 'a hostname is resolved'
             objectUnderTest.getHostName() >> 'hostX'
-        and: 'the expected delay is based on hash code with max of 3,000 ms'
-            def expectedDelay =  Math.abs('hostX'.hashCode() % 3_000)
+        and: 'the expected delay is based on hash code with max of 5,000 ms'
+            def expectedDelay =  Math.abs('hostX'.hashCode() % 5_000)
         when: 'startup delay is called'
             objectUnderTest.applyHostnameBasedStartupDelay()
         then: 'the system will sleep for expected time'
-            1 * objectUnderTest.haveALittleSleepInMs(expectedDelay) >> { /* don't really sleep */ }
+            1 * objectUnderTest.haveALittleSleepInMs(expectedDelay)
     }
 
     def 'Startup delay when hostname cannot be resolved.'() {