From f9030356434228c30a9c34230b666f94646cf136 Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Thu, 20 Jan 2022 19:57:43 +0100 Subject: [PATCH] Restart jitter to avoid crashes --- .../reactiveapi/PeriodicRestarter.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/it/tdlight/reactiveapi/PeriodicRestarter.java b/src/main/java/it/tdlight/reactiveapi/PeriodicRestarter.java index 4b465e4..59e3199 100644 --- a/src/main/java/it/tdlight/reactiveapi/PeriodicRestarter.java +++ b/src/main/java/it/tdlight/reactiveapi/PeriodicRestarter.java @@ -17,6 +17,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; @@ -30,6 +31,8 @@ public class PeriodicRestarter { private static final Logger LOG = LoggerFactory.getLogger(PeriodicRestarter.class); + private static Duration JITTER_MAX_DELAY = Duration.ofMinutes(5); + private final ReactiveApi api; private final Duration interval; private final Set restartUserIds; @@ -123,10 +126,20 @@ public class PeriodicRestarter { } private void onSessionReady(long liveId, long userId) { + Duration maxRandomDelay; + if (JITTER_MAX_DELAY.compareTo(interval) < 0) { + maxRandomDelay = JITTER_MAX_DELAY; + } else { + maxRandomDelay = interval; + } + var randomDelay = randomTime(maxRandomDelay); + + var totalDelay = interval.plus(randomDelay); + LOG.info("The session #IDU{} (liveId: {}) will be restarted at {}", userId, liveId, - Instant.now().plus(interval) + Instant.now().plus(totalDelay) ); // Restart after x time @@ -153,12 +166,19 @@ public class PeriodicRestarter { .subscribe(); } - }, interval.toMillis(), TimeUnit.MILLISECONDS); + }, totalDelay.toMillis(), TimeUnit.MILLISECONDS); disposableRef.set(disposable); var prev = closeManagedByPeriodicRestarter.put(liveId, disposable); if (prev != null) prev.dispose(); } + /** + * @return random duration from 0 to n + */ + private Duration randomTime(Duration max) { + return Duration.ofMillis(ThreadLocalRandom.current().nextInt(0, Math.toIntExact(max.toMillis()))); + } + public Mono stop() { return Mono.fromRunnable(() -> { LOG.info("Stopping periodic restarter...");