Skip to content

Commit

Permalink
MODCLUSTER-754 Modify ResetRequestSourceImpl to send STOP request whe…
Browse files Browse the repository at this point in the history
…n proxy not aware of a context

When an app server connects to a proxy for the first time or after a
disruption, it sends an INFO request to the proxy. Proxy responds with a
list of contexts that are registered for given server, and their states.
The context states returned from the proxy are compared to the actual
states of contexts on the app server, and if necessary, the server
should send ENABLE / STOP requests to bring the proxy to an up-to-date
state.

The change in this commit makes the app server send a STOP request for a
context in case when the proxy response to an INFO request doesn't
contain given context. The purpose of this STOP request is to enforce
context registration on the proxy side.
  • Loading branch information
TomasHofman committed Jun 3, 2022
1 parent 97e1b7e commit a5c1110
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,12 @@ public List<MCMPRequest> getResetRequests(Map<String, Set<VirtualHost>> response
: this.requestFactory.createDisableRequest(context));
}
} else {
if (status == ResetRequestSource.Status.ENABLED) {
if (status == ResetRequestSource.Status.ENABLED || status == null) {
// Two cases are handled here:
// 1. Context is not started, but proxy reports the context as ENABLED
// => send STOP request, so that proxy disables the context.
// 2. Context is not started, proxy is not aware of the context (status == null)
// => send STOP reqeust, so that proxy registers the context.
engineRequests.add(this.requestFactory.createStopRequest(context));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

Expand All @@ -37,6 +38,7 @@
import org.jboss.modcluster.container.Server;
import org.jboss.modcluster.config.BalancerConfiguration;
import org.jboss.modcluster.config.NodeConfiguration;
import org.jboss.modcluster.mcmp.impl.DefaultMCMPHandler;
import org.jboss.modcluster.mcmp.impl.ResetRequestSourceImpl;
import org.junit.Test;

Expand All @@ -49,7 +51,17 @@ public class ResetRequestSourceTestCase {
private final BalancerConfiguration balancerConfig = mock(BalancerConfiguration.class);
private final MCMPRequestFactory requestFactory = mock(MCMPRequestFactory.class);

private ResetRequestSource source = new ResetRequestSourceImpl(this.nodeConfig, this.balancerConfig, this.requestFactory);
private final ResetRequestSource source = new ResetRequestSourceImpl(this.nodeConfig, this.balancerConfig, this.requestFactory);

private final MCMPRequest configRequest = mock(MCMPRequest.class);
private final MCMPRequest enableRequest = mock(MCMPRequest.class);
private final MCMPRequest disableRequest = mock(MCMPRequest.class);
private final MCMPRequest stopRequest = mock(MCMPRequest.class);

private final static String JVM_ROUTE = "host1";
private final static String HOST_NAME = "host";
private final static String ALIAS1 = "alias1";
private final static String ALIAS2 = "alias2";

@Test
public void getResetRequestsNoServer() {
Expand All @@ -63,53 +75,74 @@ public void getResetRequestsNoServer() {
}

@Test
public void getResetRequests() throws Exception {
Server server = mock(Server.class);
ContextFilter contextFilter = mock(ContextFilter.class);

this.source.init(server, contextFilter);

verifyNoInteractions(server);
public void getResetRequests() {
setupMocks(true, true);

Engine engine = mock(Engine.class);
Host host = mock(Host.class);
Context context = mock(Context.class);
Context excludedContext = mock(Context.class);
MCMPRequest configRequest = mock(MCMPRequest.class);
MCMPRequest contextRequest = mock(MCMPRequest.class);
List<MCMPRequest> requests = this.source.getResetRequests(Collections
.<String, Set<ResetRequestSource.VirtualHost>> emptyMap());

when(contextFilter.getExcludedContexts(host)).thenReturn(Collections.singleton("/excluded"));
when(contextFilter.isAutoEnableContexts()).thenReturn(true);
assertEquals(2, requests.size());

when(server.getEngines()).thenReturn(Collections.singleton(engine));
assertSame(this.configRequest, requests.get(0));
assertSame(this.enableRequest, requests.get(1));
}

when(this.requestFactory.createConfigRequest(engine, this.nodeConfig, this.balancerConfig)).thenReturn(configRequest);
@Test
public void getResetRequestsDisableContexts() {
setupMocks(false, true);

when(engine.getJvmRoute()).thenReturn("host1");
when(engine.getProxyConnector()).thenReturn(mock(Connector.class));
List<MCMPRequest> requests = this.source.getResetRequests(Collections
.<String, Set<ResetRequestSource.VirtualHost>> emptyMap());

when(engine.getHosts()).thenReturn(Collections.singleton(host));
when(host.getName()).thenReturn("host");
when(host.getAliases()).thenReturn(new TreeSet<String>(Arrays.asList("alias1", "alias2")));
when(host.getContexts()).thenReturn(Arrays.asList(context, excludedContext));
when(context.getPath()).thenReturn("/context");
when(context.isStarted()).thenReturn(true);
assertEquals(2, requests.size());

when(this.requestFactory.createEnableRequest(context)).thenReturn(contextRequest);
assertSame(configRequest, requests.get(0));
assertSame(disableRequest, requests.get(1));
}

when(excludedContext.getPath()).thenReturn("/excluded");
@Test
public void getResetRequestsContextStoppedNoProxyStatus() {
setupMocks(true, false);

List<MCMPRequest> requests = this.source.getResetRequests(Collections
.<String, Set<ResetRequestSource.VirtualHost>> emptyMap());

assertEquals(2, requests.size());

assertSame(configRequest, requests.get(0));
assertSame(contextRequest, requests.get(1));
assertSame(stopRequest, requests.get(1));
}

@Test
public void getResetRequestsContextStoppedProxyStatusEnabled() {
setupMocks(true, false);

Map<String, Set<ResetRequestSource.VirtualHost>> infoResponse = createInfoResponse(
ResetRequestSource.Status.ENABLED);

List<MCMPRequest> requests = this.source.getResetRequests(infoResponse);

assertEquals(2, requests.size());

assertSame(configRequest, requests.get(0));
assertSame(stopRequest, requests.get(1));
}

@Test
public void getResetRequestsDisableContexts() throws Exception {
public void getResetRequestsContextStartedProxyStatusDisabled() {
setupMocks(true, true);
Map<String, Set<ResetRequestSource.VirtualHost>> infoResponse = createInfoResponse(
ResetRequestSource.Status.DISABLED);

List<MCMPRequest> requests = this.source.getResetRequests(infoResponse);

assertEquals(2, requests.size());

assertSame(configRequest, requests.get(0));
assertSame(enableRequest, requests.get(1));
}

private void setupMocks(boolean autoEnableContexts, boolean contextsAreStarted) {
Server server = mock(Server.class);
ContextFilter contextFilter = mock(ContextFilter.class);

Expand All @@ -121,36 +154,38 @@ public void getResetRequestsDisableContexts() throws Exception {
Host host = mock(Host.class);
Context context = mock(Context.class);
Context excludedContext = mock(Context.class);
MCMPRequest configRequest = mock(MCMPRequest.class);
MCMPRequest contextRequest = mock(MCMPRequest.class);

when(contextFilter.getExcludedContexts(host)).thenReturn(Collections.singleton("/excluded"));
when(contextFilter.isAutoEnableContexts()).thenReturn(false);
when(contextFilter.isAutoEnableContexts()).thenReturn(autoEnableContexts);

when(server.getEngines()).thenReturn(Collections.singleton(engine));

when(this.requestFactory.createConfigRequest(engine, this.nodeConfig, this.balancerConfig)).thenReturn(configRequest);

when(engine.getJvmRoute()).thenReturn("host1");
when(engine.getJvmRoute()).thenReturn(JVM_ROUTE);
when(engine.getProxyConnector()).thenReturn(mock(Connector.class));

when(engine.getHosts()).thenReturn(Collections.singleton(host));
when(host.getName()).thenReturn("host");
when(host.getAliases()).thenReturn(new TreeSet<String>(Arrays.asList("alias1", "alias2")));
when(host.getName()).thenReturn(HOST_NAME);
when(host.getAliases()).thenReturn(new TreeSet<String>(Arrays.asList(HOST_NAME, ALIAS1, ALIAS2)));
when(host.getContexts()).thenReturn(Arrays.asList(context, excludedContext));
when(context.getPath()).thenReturn("/context");
when(context.isStarted()).thenReturn(true);
when(context.isStarted()).thenReturn(contextsAreStarted);

when(this.requestFactory.createDisableRequest(context)).thenReturn(contextRequest);
when(this.requestFactory.createConfigRequest(engine, this.nodeConfig, this.balancerConfig))
.thenReturn(this.configRequest);
when(this.requestFactory.createEnableRequest(context)).thenReturn(this.enableRequest);
when(this.requestFactory.createDisableRequest(context)).thenReturn(this.disableRequest);
when(this.requestFactory.createStopRequest(context)).thenReturn(this.stopRequest);

when(excludedContext.getPath()).thenReturn("/excluded");
}

List<MCMPRequest> requests = this.source.getResetRequests(Collections
.<String, Set<ResetRequestSource.VirtualHost>> emptyMap());

assertEquals(2, requests.size());

assertSame(configRequest, requests.get(0));
assertSame(contextRequest, requests.get(1));
private Map<String, Set<ResetRequestSource.VirtualHost>> createInfoResponse(ResetRequestSource.Status contextStatus) {
DefaultMCMPHandler.VirtualHostImpl virtualHost = new DefaultMCMPHandler.VirtualHostImpl();
virtualHost.getAliases().add(HOST_NAME);
virtualHost.getAliases().add(ALIAS1);
virtualHost.getAliases().add(ALIAS2);
virtualHost.getContexts().put("/context", contextStatus);
return Collections.singletonMap(JVM_ROUTE, Collections.singleton(virtualHost));
}

}

0 comments on commit a5c1110

Please sign in to comment.