All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.launchdarkly.sdk.server.PersistentDataStoreStatusManager Maven / Gradle / Ivy

There is a newer version: 7.5.0
Show newest version
package com.launchdarkly.sdk.server;

import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.logging.LogValues;
import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider;
import com.launchdarkly.sdk.server.interfaces.DataStoreStatusProvider.Status;

import java.io.Closeable;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * Used internally to encapsulate the data store status broadcasting mechanism for PersistentDataStoreWrapper.
 * 

* This is currently only used by PersistentDataStoreWrapper, but encapsulating it in its own class helps with * clarity and also lets us reuse this logic in tests. */ final class PersistentDataStoreStatusManager implements Closeable { static final int POLL_INTERVAL_MS = 500; // visible for testing private final Consumer statusUpdater; private final ScheduledExecutorService scheduler; private final Callable statusPollFn; private final boolean refreshOnRecovery; private final LDLogger logger; private volatile boolean lastAvailable; private volatile ScheduledFuture pollerFuture; PersistentDataStoreStatusManager( boolean refreshOnRecovery, boolean availableNow, Callable statusPollFn, Consumer statusUpdater, ScheduledExecutorService sharedExecutor, LDLogger logger ) { this.refreshOnRecovery = refreshOnRecovery; this.lastAvailable = availableNow; this.statusPollFn = statusPollFn; this.statusUpdater = statusUpdater; this.scheduler = sharedExecutor; this.logger = logger; } public void close() { synchronized (this) { if (pollerFuture != null) { pollerFuture.cancel(true); pollerFuture = null; } } } void updateAvailability(boolean available) { synchronized (this) { if (lastAvailable == available) { return; } lastAvailable = available; } Status status = new Status(available, available && refreshOnRecovery); if (available) { logger.warn("Persistent store is available again"); } statusUpdater.accept(status); // If the store has just become unavailable, start a poller to detect when it comes back. If it has // become available, stop any polling we are currently doing. if (available) { synchronized (this) { if (pollerFuture != null) { pollerFuture.cancel(false); pollerFuture = null; } } } else { logger.warn("Detected persistent store unavailability; updates will be cached until it recovers"); // Start polling until the store starts working again Runnable pollerTask = new Runnable() { public void run() { try { if (statusPollFn.call()) { updateAvailability(true); } } catch (Exception e) { logger.error("Unexpected error from data store status function: {}", LogValues.exceptionSummary(e)); logger.debug(LogValues.exceptionTrace(e)); } } }; synchronized (this) { if (pollerFuture == null) { pollerFuture = scheduler.scheduleAtFixedRate( pollerTask, POLL_INTERVAL_MS, POLL_INTERVAL_MS, TimeUnit.MILLISECONDS ); } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy