Skip to content

Instantly share code, notes, and snippets.

@vladdu
Last active February 16, 2016 01:46
Show Gist options
  • Save vladdu/b8af7709e26206b1832b to your computer and use it in GitHub Desktop.
Save vladdu/b8af7709e26206b1832b to your computer and use it in GitHub Desktop.
Guava RestartableService
public class CooldownRestartPolicy extends ServiceRestartPolicy {
/**
* If restarting sooner than this, it's probably an unrecoverable error.
*/
public static final int RESTART_INTERVAL = 5000;
private long last;
private long interval = RESTART_INTERVAL;
public CooldownRestartPolicy() {
this(RESTART_INTERVAL);
}
public CooldownRestartPolicy(final long interval) {
this.interval = interval;
last = System.currentTimeMillis();
}
@Override
public void notifyRestart() {
last = System.currentTimeMillis();
}
@Override
public boolean shouldRestart() {
return System.currentTimeMillis() - last > interval;
}
}
public abstract class ServiceRestartPolicy {
/**
* Policy might want to keep track of when the latest restarts have
* happened.
*/
public void notifyRestart() {
}
abstract public boolean shouldRestart();
}
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.erlide.util.services.Provider;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Service;
public class RestartableService implements Service {
private Service delegate;
private final ServiceRestartPolicy policy;
private final Provider<Service> factory;
private final Map<Listener, Executor> listeners;
public RestartableService(final Provider<Service> factory,
final ServiceRestartPolicy policy) {
this.factory = factory;
this.policy = policy;
listeners = Maps.newHashMap();
}
private final class RestartListener extends Listener {
@Override
public void failed(final State from, final Throwable failure) {
if (policy.shouldRestart()) {
startAsync();
} else {
for (final Entry<Listener, Executor> l : listeners.entrySet()) {
l.getKey().failed(from, failure);
}
}
}
@Override
public void starting() {
for (final Entry<Listener, Executor> l : listeners.entrySet()) {
l.getKey().starting();
}
}
@Override
public void running() {
for (final Entry<Listener, Executor> l : listeners.entrySet()) {
l.getKey().running();
}
}
@Override
public void stopping(final Service.State from) {
for (final Entry<Listener, Executor> l : listeners.entrySet()) {
l.getKey().stopping(from);
}
}
@Override
public void terminated(final State from) {
for (final Entry<Listener, Executor> l : listeners.entrySet()) {
l.getKey().terminated(from);
}
}
}
/**
* Used for testing only.
*
* @return delegate
*/
public Service getDelegate() {
return delegate;
}
@Override
public Service startAsync() {
delegate = factory.get();
delegate.addListener(new RestartListener(), MoreExecutors.sameThreadExecutor());
delegate.startAsync();
policy.notifyRestart();
return this;
}
@Override
public boolean isRunning() {
return delegate.isRunning();
}
@Override
public State state() {
return delegate.state();
}
@Override
public Service stopAsync() {
delegate.stopAsync();
return this;
}
@Override
public void awaitRunning() {
delegate.awaitRunning();
}
@Override
public void awaitRunning(final long timeout, final TimeUnit unit)
throws TimeoutException {
delegate.awaitRunning(timeout, unit);
}
@Override
public void awaitTerminated() {
delegate.awaitTerminated();
}
@Override
public void awaitTerminated(final long timeout, final TimeUnit unit)
throws TimeoutException {
delegate.awaitTerminated(timeout, unit);
}
@Override
public Throwable failureCause() {
return delegate.failureCause();
}
@Override
public void addListener(final Listener listener, final Executor executor) {
synchronized (listeners) {
listeners.put(listener, executor);
}
}
}
public abstract class ServiceRestartPolicy {
/**
* Policy might want to keep track of when the latest restarts have
* happened.
*/
public void notifyRestart() {
}
abstract public boolean shouldRestart();
}
@JLLeitschuh
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment