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

io.split.engine.experiments.SplitSynchronizationTask Maven / Gradle / Ivy

The newest version!
package io.split.engine.experiments;

import io.split.storages.SplitCacheProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.util.List;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static io.split.client.utils.SplitExecutorFactory.buildSingleThreadScheduledExecutor;

/**
 * Provides an instance of RefreshableExperimentFetcher that is guaranteed to be a singleton.
 *
 * @author adil
 */
public class SplitSynchronizationTask implements SyncTask, Closeable {
    private static final Logger _log = LoggerFactory.getLogger(SplitSynchronizationTask.class);

    private final AtomicReference _splitFetcher = new AtomicReference<>();
    private final AtomicReference _splitCacheProducer = new AtomicReference();
    private final AtomicReference _executorService = new AtomicReference<>();
    private final AtomicLong _refreshEveryNSeconds;
    private final ScheduledExecutorService _scheduledExecutorService;
    private final AtomicBoolean _running;

    private ScheduledFuture _scheduledFuture;

    public SplitSynchronizationTask(SplitFetcher splitFetcher, SplitCacheProducer splitCachesplitCacheProducer, long refreshEveryNSeconds,
                                    ThreadFactory threadFactory) {
        _splitFetcher.set(checkNotNull(splitFetcher));
        _splitCacheProducer.set(checkNotNull(splitCachesplitCacheProducer));
        checkArgument(refreshEveryNSeconds >= 0L);
        _refreshEveryNSeconds = new AtomicLong(refreshEveryNSeconds);

        _scheduledExecutorService = buildSingleThreadScheduledExecutor(threadFactory, "split-splitFetcher-%d");
        _executorService.set(_scheduledExecutorService);

        _running = new AtomicBoolean();
    }

    public void start() {
        if (_running.getAndSet(true)) {
            _log.debug("Splits PeriodicFetching is running...");
            return;
        }

        _log.debug("Starting PeriodicFetching Feature flags ...");
        _scheduledFuture = _scheduledExecutorService.scheduleWithFixedDelay(_splitFetcher.get(), 0L, _refreshEveryNSeconds.get(), TimeUnit.SECONDS);
    }

    public void stop() {
        if (!_running.getAndSet(false) || _scheduledFuture == null) {
            _log.debug("Splits PeriodicFetching not running...");
            return;
        }

        _scheduledFuture.cancel(false);
        _log.debug("Stopped PeriodicFetching Feature flags ...");
    }

    @Override
    public void close() {
        if (_executorService.get() == null) {
            return;
        }

        if (_splitFetcher.get() != null) {
            _splitCacheProducer.get().clear();
        }

        stop();

        ScheduledExecutorService scheduledExecutorService = _executorService.get();
        if (scheduledExecutorService.isShutdown()) {
            return;
        }

        scheduledExecutorService.shutdown();
        try {
            if (!scheduledExecutorService.awaitTermination(2L, TimeUnit.SECONDS)) { //optional *
                _log.warn("Executor did not terminate in the specified time.");
                List droppedTasks = scheduledExecutorService.shutdownNow(); //optional **
                _log.warn("Executor was abruptly shut down. These tasks will not be executed: " + droppedTasks);
            }
        } catch (InterruptedException e) {
            // reset the interrupt.
            _log.warn("Shutdown hook for feature flag fetchers has been interrupted");
            Thread.currentThread().interrupt();
        }
    }

    @Override
    public boolean isRunning() {
        return _running.get();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy