-
-
Save JLLeitschuh/90e7b26eae4d69496e7d to your computer and use it in GitHub Desktop.
Guava RestartableService
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CooldownRestartPolicy implements 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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 Supplier<Service> factory; | |
private final Map<Listener, Executor> listeners; | |
public RestartableService(final Supplier<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); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface ServiceRestartPolicy { | |
/** | |
* Policy might want to keep track of when the latest restarts have | |
* happened. | |
*/ | |
default void notifyRestart() { | |
/* no-op */ | |
} | |
boolean shouldRestart(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment