mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 08:55:44 +01:00
added RestartStrategies to be able to swap the context recreation strategy
This commit is contained in:
@@ -37,7 +37,6 @@ import com.github.legman.Subscribe;
|
||||
import com.google.inject.servlet.GuiceFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.event.RecreateEventBusEvent;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
@@ -50,63 +49,29 @@ import javax.servlet.ServletException;
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class BootstrapContextFilter extends GuiceFilter
|
||||
{
|
||||
public class BootstrapContextFilter extends GuiceFilter {
|
||||
|
||||
/**
|
||||
* the logger for BootstrapContextFilter
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(BootstrapContextFilter.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BootstrapContextFilter.class);
|
||||
|
||||
private final BootstrapContextListener listener = new BootstrapContextListener();
|
||||
|
||||
/**
|
||||
* Restart the whole webapp context.
|
||||
*
|
||||
*
|
||||
* @param event restart event
|
||||
*
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Subscribe
|
||||
public void handleRestartEvent(RestartEvent event) throws ServletException
|
||||
{
|
||||
logger.warn("received restart event from {} with reason: {}",
|
||||
event.getCause(), event.getReason());
|
||||
|
||||
if (filterConfig == null)
|
||||
{
|
||||
logger.error("filter config is null, scm-manager is not initialized");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("destroy filter pipeline, because of a received restart event");
|
||||
destroy();
|
||||
|
||||
logger.warn("send recreate eventbus event");
|
||||
ScmEventBus.getInstance().post(new RecreateEventBusEvent());
|
||||
ScmEventBus.getInstance().register(this);
|
||||
|
||||
logger.warn("reinitialize filter pipeline, because of a received restart event");
|
||||
initGuice();
|
||||
}
|
||||
}
|
||||
/** Field description */
|
||||
private FilterConfig filterConfig;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
this.filterConfig = filterConfig;
|
||||
|
||||
initGuice();
|
||||
|
||||
logger.info("register for restart events");
|
||||
LOG.info("register for restart events");
|
||||
ScmEventBus.getInstance().register(this);
|
||||
}
|
||||
|
||||
public void initGuice() throws ServletException {
|
||||
private void initGuice() throws ServletException {
|
||||
super.init(filterConfig);
|
||||
|
||||
listener.contextInitialized(new ServletContextEvent(filterConfig.getServletContext()));
|
||||
@@ -119,8 +84,39 @@ public class BootstrapContextFilter extends GuiceFilter
|
||||
ServletContextCleaner.cleanup(filterConfig.getServletContext());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
/**
|
||||
* Restart SCM-Manager.
|
||||
*
|
||||
* @param event restart event
|
||||
*/
|
||||
@Subscribe
|
||||
public void handleRestartEvent(RestartEvent event) {
|
||||
LOG.warn("received restart event from {} with reason: {}",
|
||||
event.getCause(), event.getReason());
|
||||
|
||||
if (filterConfig == null) {
|
||||
LOG.error("filter config is null, scm-manager is not initialized");
|
||||
} else {
|
||||
RestartStrategy restartStrategy = RestartStrategy.get();
|
||||
restartStrategy.restart(new GuiceInjectionContext());
|
||||
}
|
||||
}
|
||||
|
||||
private class GuiceInjectionContext implements RestartStrategy.InjectionContext {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
try {
|
||||
BootstrapContextFilter.this.initGuice();
|
||||
} catch (ServletException e) {
|
||||
throw new IllegalStateException("failed to initialize guice", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
BootstrapContextFilter.this.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
private FilterConfig filterConfig;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package sonia.scm.boot;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.event.RecreateEventBusEvent;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Restart strategy implementation which destroy the injection context and re initialize it.
|
||||
*/
|
||||
public class InjectionContextRestartStrategy implements RestartStrategy {
|
||||
|
||||
private static final AtomicLong INSTANCE_COUNTER = new AtomicLong();
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InjectionContextRestartStrategy.class);
|
||||
|
||||
private long waitInMs = 250L;
|
||||
|
||||
@VisibleForTesting
|
||||
void setWaitInMs(long waitInMs) {
|
||||
this.waitInMs = waitInMs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restart(InjectionContext context) {
|
||||
LOG.warn("destroy injection context");
|
||||
context.destroy();
|
||||
|
||||
LOG.warn("send recreate eventbus event");
|
||||
ScmEventBus.getInstance().post(new RecreateEventBusEvent());
|
||||
|
||||
// restart context delayed, to avoid timing problems
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(waitInMs);
|
||||
|
||||
LOG.warn("reinitialize injection context");
|
||||
context.initialize();
|
||||
|
||||
LOG.debug("re register injection context for events");
|
||||
ScmEventBus.getInstance().register(context);
|
||||
} catch ( Exception ex) {
|
||||
LOG.error("failed to restart", ex);
|
||||
}
|
||||
}, "Delayed-Restart-" + INSTANCE_COUNTER.incrementAndGet()).start();
|
||||
|
||||
}
|
||||
}
|
||||
38
scm-webapp/src/main/java/sonia/scm/boot/RestartStrategy.java
Normal file
38
scm-webapp/src/main/java/sonia/scm/boot/RestartStrategy.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package sonia.scm.boot;
|
||||
|
||||
/**
|
||||
* Strategy for restarting SCM-Manager.
|
||||
*/
|
||||
public interface RestartStrategy {
|
||||
|
||||
/**
|
||||
* Context for Injection in SCM-Manager.
|
||||
*/
|
||||
interface InjectionContext {
|
||||
/**
|
||||
* Initialize the injection context.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Destroys the injection context.
|
||||
*/
|
||||
void destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart SCM-Manager.
|
||||
* @param context injection context
|
||||
*/
|
||||
void restart(InjectionContext context);
|
||||
|
||||
/**
|
||||
* Returns the configured strategy.
|
||||
*
|
||||
* @return configured strategy
|
||||
*/
|
||||
static RestartStrategy get() {
|
||||
return new InjectionContextRestartStrategy();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user