use of net.dempsy.router.group.intern.GroupDetails in project Dempsy by Dempsy.
the class ClusterGroupInbound method maybeStart.
private synchronized void maybeStart(final Infrastructure infra, final Proxy ib) {
if (// this should not be possible
started)
throw new IllegalStateException("start() called on a group routing strategy more times than there are clusters in the group.");
if (ib.groupName == null)
throw new IllegalStateException("The group name isn't set on the inbound for " + ib.clusterId + ". This shouldn't be possible. Was the typeId specified correctly?");
if (groupDetails == null) {
groupDetails = new GroupDetails(ib.groupName, ib.address.node);
caByCluster = new HashMap<>();
} else if (!groupDetails.groupName.equals(ib.groupName))
throw new IllegalStateException("The group name for " + ib.clusterId + " is " + ib.groupName + " but doesn't match prevous group names supposedly in the same group: " + groupDetails.groupName);
else if (!groupDetails.node.equals(ib.address.node))
throw new IllegalStateException("The node address for " + ib.clusterId + " is " + ib.address.node + " but doesn't match prevous group names supposedly in the same group: " + groupDetails.node);
if (caByCluster.containsKey(ib.clusterId.clusterName))
throw new IllegalStateException("There appears to be two inbounds both configured with the same cluster id:" + ib.clusterId);
caByCluster.put(ib.clusterId.clusterName, ib.address);
if (!inbounds.contains(ib))
throw new IllegalStateException("Not all routing strategies that are part of this group seemed to have had setContainerDetails called prior to start.");
numStarted++;
if (numStarted == inbounds.size()) {
// if all of the proxies have checked in then we need to go ahead and start
started = true;
final int totalShards = Integer.parseInt(infra.getConfigValue(ClusterGroupInbound.class, Utils.CONFIG_KEY_TOTAL_SHARDS, Utils.DEFAULT_TOTAL_SHARDS));
final int minNodes = Integer.parseInt(infra.getConfigValue(ClusterGroupInbound.class, Utils.CONFIG_KEY_MIN_NODES, Utils.DEFAULT_MIN_NODES));
if (Integer.bitCount(totalShards) != 1)
throw new IllegalArgumentException("The configuration property \"" + Utils.CONFIG_KEY_TOTAL_SHARDS + "\" must be set to a power of 2. It's currently set to " + totalShards);
this.mask = totalShards - 1;
groupDetails.fillout(caByCluster);
utils = new Utils<GroupDetails>(infra, groupDetails.groupName, groupDetails);
// subscriber first because it registers as a node. If there's no nodes
// there's nothing for the leader to do.
subscriber = new Subscriber<GroupDetails>(utils, infra, isRunning, new CompoundKeyspaceListener(inbounds.stream().map(p -> p.listener).collect(Collectors.toList())), totalShards);
subscriber.process();
leader = new Leader<GroupDetails>(utils, totalShards, minNodes, infra, isRunning, GroupDetails[]::new);
leader.process();
inbounds.forEach(p -> p.setup(subscriber, utils, mask));
}
}
use of net.dempsy.router.group.intern.GroupDetails in project Dempsy by Dempsy.
the class ClusterGroupRouter method selectDestinationForMessage.
@Override
public ContainerAddress selectDestinationForMessage(final KeyedMessageWithType message) {
final GroupDetails[] destinations = this.destinations.get();
if (destinations == null)
throw new DempsyException("It appears the " + ClusterGroupRouter.class.getSimpleName() + " strategy for the message key " + SafeString.objectDescription(message != null ? message.key : null) + " is being used prior to initialization or after a failure.");
if (containerIndex < 0) {
containerIndex = getIndex(destinations, clusterName);
if (containerIndex < 0)
return null;
}
final GroupDetails cur = destinations[utils.determineShard(message.key, mask)];
return cur.containerAddresses[containerIndex];
}
use of net.dempsy.router.group.intern.GroupDetails in project Dempsy by Dempsy.
the class ClusterGroupRouter method getIndex.
private static int getIndex(final GroupDetails[] destinations, final String clustername) {
final GroupDetails gd = Arrays.stream(destinations).filter(g -> g != null).findAny().orElse(null);
if (gd == null)
return -1;
final Integer ret = gd.clusterIndicies.get(clustername);
return ret == null ? -1 : ret.intValue();
}
use of net.dempsy.router.group.intern.GroupDetails in project Dempsy by Dempsy.
the class ClusterGroupRouter method isReady.
/**
* This makes sure all of the destinations are full.
*/
boolean isReady() {
final GroupDetails[] ds = destinations.get();
if (ds == null)
return false;
for (final GroupDetails d : ds) if (d == null)
return false;
// this method is only called in tests and this needs to be true there.
final boolean ret = ds.length != 0 && getIndex(ds, clusterName) >= 0;
if (ret && LOGGER.isDebugEnabled())
LOGGER.debug("at {} to {} is Ready " + shorthand(cvrt(ds, clusterName)), thisNodeId, clusterId);
return ret;
}
use of net.dempsy.router.group.intern.GroupDetails in project Dempsy by Dempsy.
the class TestGroupRoutingStrategy method testInboundWithOutbound.
@Test
public void testInboundWithOutbound() throws Exception {
final int numShardsToExpect = Integer.parseInt(Utils.DEFAULT_TOTAL_SHARDS);
final String groupName = "testInboundWithOutbound";
final Manager<RoutingStrategy.Inbound> manager = new RoutingInboundManager();
try (final RoutingStrategy.Inbound ib = manager.getAssociatedInstance(ClusterGroupInbound.class.getPackage().getName() + ":" + groupName)) {
final ClusterId cid = setTestName("testInboundWithOutbound");
final NodeAddress na = new DummyNodeAddress("here");
final ContainerAddress oca = new ContainerAddress(na, 0);
final Infrastructure infra = makeInfra(session, sched);
final GroupDetails ogd = new GroupDetails(groupName, na);
final Map<String, ContainerAddress> ocaiByCluster = new HashMap<>();
ocaiByCluster.put(cid.clusterName, oca);
ogd.fillout(ocaiByCluster);
final Utils<GroupDetails> msutils = new Utils<>(infra, groupName, ogd);
ib.setContainerDetails(cid, oca, (l, m) -> {
});
ib.start(infra);
checkForShardDistribution(session, msutils, numShardsToExpect, 1);
try (final ClusterInfoSession ses2 = sessFact.createSession();
final RoutingStrategyManager obman = chain(new RoutingStrategyManager(), o -> o.start(makeInfra(ses2, sched)));
final RoutingStrategy.Factory obf = obman.getAssociatedInstance(ClusterGroupInbound.class.getPackage().getName() + ":" + groupName)) {
obf.start(makeInfra(ses2, sched));
assertTrue(poll(o -> obf.isReady()));
final RoutingStrategy.Router ob = obf.getStrategy(cid);
assertTrue(poll(o -> obf.isReady()));
final KeyedMessageWithType km = new KeyedMessageWithType(new Object(), new Object(), "");
assertTrue(poll(o -> ob.selectDestinationForMessage(km) != null));
final ContainerAddress ca = ob.selectDestinationForMessage(km);
assertNotNull(ca);
assertEquals("here", ((DummyNodeAddress) ca.node).name);
// now disrupt the session
session.close();
// the destination should clear until a new one runs
// NO: destination will not necessarily clear.
// poll(o -> ob.selectDestinationForMessage(km) == null);
final ContainerAddress nca = new ContainerAddress(new DummyNodeAddress("here-again"), 0);
ogd.fillout(ocaiByCluster);
try (ClusterInfoSession ses3 = sessFact.createSession();
RoutingStrategy.Inbound ib2 = new RoutingInboundManager().getAssociatedInstance(ClusterGroupInbound.class.getPackage().getName() + ":" + groupName)) {
ib2.setContainerDetails(cid, nca, (l, m) -> {
});
ib2.start(makeInfra(ses3, sched));
assertTrue(poll(o -> ob.selectDestinationForMessage(km) != null));
}
}
}
}
Aggregations