
io.joynr.runtime.ShutdownNotifier Maven / Gradle / Ivy
/*
* #%L
* %%
* Copyright (C) 2011 - 2017 BMW Car IT GmbH
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.joynr.runtime;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Singleton;
@Singleton
public class ShutdownNotifier {
private static final Logger logger = LoggerFactory.getLogger(ShutdownNotifier.class);
/**
* Timeout in seconds after which the {@link #prepareForShutdown()} will stop waiting for the operation to
* complete and return control to the caller. Note that this doesn't guarantee that the processes triggered
* by calling {@link #prepareForShutdown()} are also cancelled - they may still be running in the background.
*/
private static final String PROPERTY_PREPARE_FOR_SHUTDOWN_TIMEOUT = "joynr.runtime.prepareforshutdowntimeout";
private List shutdownListeners = new LinkedList<>();
@Inject(optional = true)
@Named(PROPERTY_PREPARE_FOR_SHUTDOWN_TIMEOUT)
private int prepareForShutdownTimeoutSec = 5;
/**
* register to have the listener's shutdown method called at system shutdown
* NOTE: no shutdown order is guaranteed.
* @param shutdownListener
*/
public void registerForShutdown(ShutdownListener shutdownListener) {
shutdownListeners.add(0, shutdownListener);
}
/**
* register to have the listener's shutdown method called at system shutdown
* as one of the last listeners. It is a partial ordering and ensures that this
* listener's shutdown will be called after all listeners registered using
* {@link #registerForShutdown(ShutdownListener)}.
* NOTE: Listeners who manage some executor service should use this method.
* @param shutdownListener
*/
public void registerToBeShutdownAsLast(ShutdownListener shutdownListener) {
shutdownListeners.add(shutdownListener);
}
/**
* Will call {@link ShutdownListener#prepareForShutdown()} for each {@link #registerForShutdown(ShutdownListener) registered listener}
* asynchronously, and waiting a total of five seconds for all to complete or will then timeout without waiting.
*/
public void prepareForShutdown() {
Collection> prepareShutdownFutures = shutdownListeners.stream()
.map(shutdownListener -> CompletableFuture.runAsync(() -> shutdownListener.prepareForShutdown()))
.collect(Collectors.toList());
try {
CompletableFuture.allOf(prepareShutdownFutures.toArray(new CompletableFuture[prepareShutdownFutures.size()]))
.get(prepareForShutdownTimeoutSec, TimeUnit.SECONDS);
} catch (Exception e) {
logger.error("Exception occurred while preparing shutdown.", e);
}
}
/**
* Calls {@link ShutdownListener#shutdown()} for each {@link #registerForShutdown(ShutdownListener) registered listener}
* synchronously in turn.
*/
public void shutdown() {
shutdownListeners.forEach(shutdownListener -> {
logger.trace("shutting down {}", shutdownListener);
try {
shutdownListener.shutdown();
} catch (Exception e) {
logger.error("error shutting down {}: {}", shutdownListener, e.getMessage());
}
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy