2019-06-25 08:36:57 +02:00
|
|
|
package sonia.scm.lifecycle;
|
2019-06-19 11:53:58 +02:00
|
|
|
|
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
import sonia.scm.event.RecreateEventBusEvent;
|
|
|
|
|
import sonia.scm.event.ScmEventBus;
|
2019-11-21 16:20:55 +01:00
|
|
|
import sonia.scm.event.ShutdownEventBusEvent;
|
2019-06-19 11:53:58 +02:00
|
|
|
|
|
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
|
|
|
|
|
|
/**
|
2020-02-12 12:13:10 +01:00
|
|
|
* Restart strategy which tries to free, every resource used by the context, starts gc and re initializes the context.
|
2019-06-19 11:53:58 +02:00
|
|
|
*/
|
2020-02-12 12:13:10 +01:00
|
|
|
class InjectionContextRestartStrategy implements RestartStrategy {
|
|
|
|
|
|
|
|
|
|
static final String NAME = "context";
|
2019-06-19 11:53:58 +02:00
|
|
|
|
2019-11-21 16:20:55 +01:00
|
|
|
private static final String DISABLE_RESTART_PROPERTY = "sonia.scm.restart.disable";
|
|
|
|
|
private static final String WAIT_PROPERTY = "sonia.scm.restart.wait";
|
|
|
|
|
private static final String DISABLE_GC_PROPERTY = "sonia.scm.restart.disable-gc";
|
|
|
|
|
|
2019-06-19 11:53:58 +02:00
|
|
|
private static final AtomicLong INSTANCE_COUNTER = new AtomicLong();
|
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(InjectionContextRestartStrategy.class);
|
|
|
|
|
|
2019-11-21 16:20:55 +01:00
|
|
|
private boolean restartEnabled = !Boolean.getBoolean(DISABLE_RESTART_PROPERTY);
|
|
|
|
|
private long waitInMs = Integer.getInteger(WAIT_PROPERTY, 250);
|
|
|
|
|
private boolean gcEnabled = !Boolean.getBoolean(DISABLE_GC_PROPERTY);
|
|
|
|
|
|
|
|
|
|
private final ClassLoader webAppClassLoader;
|
|
|
|
|
|
|
|
|
|
InjectionContextRestartStrategy(ClassLoader webAppClassLoader) {
|
|
|
|
|
this.webAppClassLoader = webAppClassLoader;
|
|
|
|
|
}
|
2019-06-19 11:53:58 +02:00
|
|
|
|
|
|
|
|
@VisibleForTesting
|
|
|
|
|
void setWaitInMs(long waitInMs) {
|
|
|
|
|
this.waitInMs = waitInMs;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-21 16:20:55 +01:00
|
|
|
@VisibleForTesting
|
|
|
|
|
void setGcEnabled(boolean gcEnabled) {
|
|
|
|
|
this.gcEnabled = gcEnabled;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-19 11:53:58 +02:00
|
|
|
@Override
|
|
|
|
|
public void restart(InjectionContext context) {
|
2019-11-21 16:20:55 +01:00
|
|
|
stop(context);
|
|
|
|
|
if (restartEnabled) {
|
|
|
|
|
start(context);
|
|
|
|
|
} else {
|
|
|
|
|
LOG.warn("restarting context is disabled");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("squid:S1215") // suppress explicit gc call warning
|
|
|
|
|
private void start(InjectionContext context) {
|
|
|
|
|
LOG.debug("use WebAppClassLoader as ContextClassLoader, to avoid ClassLoader leaks");
|
|
|
|
|
Thread.currentThread().setContextClassLoader(webAppClassLoader);
|
2019-06-19 11:53:58 +02:00
|
|
|
|
|
|
|
|
LOG.warn("send recreate eventbus event");
|
|
|
|
|
ScmEventBus.getInstance().post(new RecreateEventBusEvent());
|
|
|
|
|
|
|
|
|
|
// restart context delayed, to avoid timing problems
|
|
|
|
|
new Thread(() -> {
|
|
|
|
|
try {
|
2019-11-21 16:20:55 +01:00
|
|
|
if (gcEnabled){
|
|
|
|
|
LOG.info("call gc to clean up memory from old instances");
|
|
|
|
|
System.gc();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG.info("wait {}ms before re starting the context", waitInMs);
|
2019-06-19 11:53:58 +02:00
|
|
|
Thread.sleep(waitInMs);
|
|
|
|
|
|
|
|
|
|
LOG.warn("reinitialize injection context");
|
|
|
|
|
context.initialize();
|
|
|
|
|
|
2019-06-20 14:58:32 +02:00
|
|
|
LOG.debug("register injection context on new eventbus");
|
2019-06-19 11:53:58 +02:00
|
|
|
ScmEventBus.getInstance().register(context);
|
|
|
|
|
} catch ( Exception ex) {
|
|
|
|
|
LOG.error("failed to restart", ex);
|
|
|
|
|
}
|
|
|
|
|
}, "Delayed-Restart-" + INSTANCE_COUNTER.incrementAndGet()).start();
|
2019-11-21 16:20:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void stop(InjectionContext context) {
|
|
|
|
|
LOG.warn("destroy injection context");
|
|
|
|
|
context.destroy();
|
2019-06-19 11:53:58 +02:00
|
|
|
|
2019-11-21 16:20:55 +01:00
|
|
|
if (!restartEnabled) {
|
|
|
|
|
// shutdown eventbus, but do this only if restart is disabled
|
|
|
|
|
ScmEventBus.getInstance().post(new ShutdownEventBusEvent());
|
|
|
|
|
}
|
2019-06-19 11:53:58 +02:00
|
|
|
}
|
|
|
|
|
}
|