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

io.quarkus.runtime.shutdown.ShutdownRecorder Maven / Gradle / Ivy

There is a newer version: 3.17.5
Show newest version
package io.quarkus.runtime.shutdown;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.jboss.logging.Logger;

import io.quarkus.runtime.annotations.Recorder;

@Recorder
public class ShutdownRecorder {

    private static final Logger log = Logger.getLogger(ShutdownRecorder.class);

    private static volatile List shutdownListeners;
    private static volatile ShutdownConfig shutdownConfig;
    private static volatile boolean delayEnabled;

    public ShutdownRecorder(ShutdownConfig shutdownConfig) {
        ShutdownRecorder.shutdownConfig = shutdownConfig;
    }

    public void setListeners(List listeners, boolean delayEnabled) {
        shutdownListeners = Optional.ofNullable(listeners).orElseGet(List::of);
        ShutdownRecorder.delayEnabled = delayEnabled;
    }

    public static void runShutdown() {
        if (shutdownListeners == null) { // when QUARKUS_INIT_AND_EXIT is used, ShutdownRecorder#setListeners has not been called
            return;
        }
        log.debug("Attempting to gracefully shutdown.");
        try {
            executePreShutdown();
            waitForDelay();
            executeShutdown();
        } catch (Throwable e) {
            log.error("Graceful shutdown failed", e);
        }
    }

    private static void executePreShutdown() throws InterruptedException {
        CountDownLatch preShutdown = new CountDownLatch(shutdownListeners.size());
        for (ShutdownListener i : shutdownListeners) {
            i.preShutdown(new LatchShutdownNotification(preShutdown));
        }
        preShutdown.await();
    }

    private static void waitForDelay() {
        if (delayEnabled && shutdownConfig.isDelaySet()) {
            try {
                Thread.sleep(shutdownConfig.delay.get().toMillis());
            } catch (InterruptedException e) {
                log.error("Interrupted while waiting for delay, continuing to shutdown immediately");
            }
        }
    }

    private static void executeShutdown() throws InterruptedException {
        CountDownLatch shutdown = new CountDownLatch(shutdownListeners.size());
        for (ShutdownListener i : shutdownListeners) {
            i.shutdown(new LatchShutdownNotification(shutdown));
        }
        if (shutdownConfig.isShutdownTimeoutSet()
                && !shutdown.await(shutdownConfig.timeout.get().toMillis(), TimeUnit.MILLISECONDS)) {
            log.error("Timed out waiting for graceful shutdown, shutting down anyway.");
        }
    }

    private static class LatchShutdownNotification implements ShutdownListener.ShutdownNotification {
        private final CountDownLatch latch;

        public LatchShutdownNotification(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void done() {
            latch.countDown();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy