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

io.deephaven.server.util.Scheduler Maven / Gradle / Ivy

The newest version!
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.server.util;

import io.deephaven.base.clock.Clock;
import io.deephaven.util.annotations.VisibleForTesting;
import org.jetbrains.annotations.NotNull;

import java.time.Instant;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * The Scheduler is used to schedule tasks that should execute at a future time.
 */
public interface Scheduler extends Clock {

    /**
     * Schedule this task to run at the specified time.
     *
     * @param epochMillis when to run this task
     * @param command the task to run
     */
    void runAtTime(long epochMillis, @NotNull Runnable command);

    /**
     * Schedule this task to run at the specified time.
     *
     * @param delayMs how long to delay before running this task (in milliseconds)
     * @param command the task to run
     */
    void runAfterDelay(long delayMs, @NotNull Runnable command);

    /**
     * Schedule this task to run immediately.
     *
     * @param command the task to run
     */
    void runImmediately(@NotNull Runnable command);

    /**
     * Schedule this task to run immediately, under the exclusive UGP lock.
     *
     * @param command the task to run
     */
    void runSerially(@NotNull Runnable command);

    /**
     * @return whether this scheduler is being run for tests.
     */
    default boolean inTestMode() {
        return false;
    }

    class DelegatingImpl implements Scheduler {

        private final ExecutorService serialDelegate;
        private final ScheduledExecutorService concurrentDelegate;
        private final Clock clock;

        public DelegatingImpl(ExecutorService serialExecutor, ScheduledExecutorService concurrentExecutor,
                Clock clock) {
            this.serialDelegate = Objects.requireNonNull(serialExecutor);
            this.concurrentDelegate = Objects.requireNonNull(concurrentExecutor);
            this.clock = Objects.requireNonNull(clock);
        }

        @VisibleForTesting
        public void shutdown() throws InterruptedException {
            concurrentDelegate.shutdownNow();
            serialDelegate.shutdownNow();
            if (!concurrentDelegate.awaitTermination(5, TimeUnit.SECONDS)) {
                throw new RuntimeException("concurrentDelegate not shutdown within 5 seconds");
            }
            if (!serialDelegate.awaitTermination(5, TimeUnit.SECONDS)) {
                throw new RuntimeException("serialDelegate not shutdown within 5 seconds");
            }
        }

        @Override
        public long currentTimeMillis() {
            return clock.currentTimeMillis();
        }

        @Override
        public long currentTimeMicros() {
            return clock.currentTimeMicros();
        }

        @Override
        public long currentTimeNanos() {
            return clock.currentTimeNanos();
        }

        @Override
        public Instant instantNanos() {
            return clock.instantNanos();
        }

        @Override
        public Instant instantMillis() {
            return clock.instantMillis();
        }

        @Override
        public void runAtTime(long epochMillis, @NotNull Runnable command) {
            runAfterDelay(epochMillis - clock.currentTimeMillis(), command);
        }

        @Override
        public void runImmediately(@NotNull final Runnable command) {
            runAfterDelay(0, command);
        }

        @Override
        public void runAfterDelay(final long delayMs, @NotNull final Runnable command) {
            concurrentDelegate.schedule(command, delayMs, TimeUnit.MILLISECONDS);
        }

        @Override
        public void runSerially(@NotNull final Runnable command) {
            serialDelegate.submit(command);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy