Search in sources :

Example 1 with ContainerAddress

use of net.dempsy.router.RoutingStrategy.ContainerAddress in project Dempsy by Dempsy.

the class OutgoingDispatcher method dispatch.

@Override
public void dispatch(final KeyedMessageWithType message) {
    boolean messageSentSomewhere = false;
    try {
        ApplicationState tmp = outbounds.get();
        // if we're in the midst of an update then we really want to wait for the new state.
        while (tmp == null) {
            if (!isRunning.get()) {
                LOGGER.debug("Router dispatch called while stopped.");
                return;
            }
            if (// however, if we never were ready then we're not in the midst
            !isReady.get())
                // of an update.
                throw new IllegalStateException("Dispatch used before Router is ready.");
            // let the other threads do their thing. Maybe we'll be updated sooner.
            Thread.yield();
            // are we updated yet?
            tmp = outbounds.get();
        }
        final ApplicationState cur = tmp;
        final Map<String, RoutingStrategy.Router[]> outboundsByMessageType = cur.outboundsByMessageType;
        // =================================================================================
        // For each message type, determine the set of Routers. The goal of this loop is to set
        // 'containerByNodeAddress'
        final Map<NodeAddress, ContainerAddress> containerByNodeAddress = new HashMap<>();
        for (final String mt : message.messageTypes) {
            final RoutingStrategy.Router[] routers = outboundsByMessageType.get(mt);
            if (routers == null)
                LOGGER.trace("No cluster that handles messages of type {}", mt);
            else {
                // the set of ContainerAddresses that this message will be sent to.
                for (int i = 0; i < routers.length; i++) {
                    final ContainerAddress ca = routers[i].selectDestinationForMessage(message);
                    // it's possible 'ca' is null when we don't know where to send the message.
                    if (ca == null)
                        LOGGER.debug("No way to send the message {} to specific cluster for the time being", message.message);
                    else {
                        // When the message will be sent to 2 different clusters, but both clusters
                        // are hosted in the same node, then we send 1 message to 1 ContainerAddress
                        // where the 'clusters' field contains both container ids.
                        final ContainerAddress already = containerByNodeAddress.get(ca.node);
                        if (already != null) {
                            final int[] ia = new int[already.clusters.length + ca.clusters.length];
                            System.arraycopy(already.clusters, 0, ia, 0, already.clusters.length);
                            System.arraycopy(ca.clusters, 0, ia, already.clusters.length, ca.clusters.length);
                            containerByNodeAddress.put(ca.node, new ContainerAddress(ca.node, ia));
                        } else
                            containerByNodeAddress.put(ca.node, ca);
                    }
                }
            }
        }
        for (final Map.Entry<NodeAddress, ContainerAddress> e : containerByNodeAddress.entrySet()) {
            final NodeAddress curNode = e.getKey();
            final ContainerAddress curAddr = e.getValue();
            final RoutedMessage toSend = new RoutedMessage(curAddr.clusters, message.key, message.message);
            if (curNode.equals(thisNode)) {
                // this shouldn't count since Router is an OUTGOING class
                nodeReciever.feedbackLoop(toSend, false);
                messageSentSomewhere = true;
            } else {
                final Sender sender = cur.getSender(curNode);
                if (sender == null) {
                    // router update is probably behind the routing strategy update
                    if (isRunning.get())
                        LOGGER.error("Couldn't send message to " + curNode + " from " + thisNodeId + " because there's no " + Sender.class.getSimpleName());
                } else {
                    sender.send(toSend);
                    messageSentSomewhere = true;
                }
            }
        }
        if (containerByNodeAddress.size() == 0) {
            if (LOGGER.isTraceEnabled())
                LOGGER.trace("There appears to be no valid destination addresses for the message {}", SafeString.objectDescription(message.message));
        }
    } finally {
        if (!messageSentSomewhere)
            statsCollector.messageNotSent();
    }
}
Also used : HashMap(java.util.HashMap) ApplicationState(net.dempsy.intern.ApplicationState) RoutedMessage(net.dempsy.transport.RoutedMessage) SafeString(net.dempsy.util.SafeString) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) Sender(net.dempsy.transport.Sender) RoutingStrategy(net.dempsy.router.RoutingStrategy) NodeAddress(net.dempsy.transport.NodeAddress) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with ContainerAddress

use of net.dempsy.router.RoutingStrategy.ContainerAddress in project Dempsy by Dempsy.

the class TestGroupRoutingStrategy method testInboundDoubleHappyPathRegister.

@Test
public void testInboundDoubleHappyPathRegister() throws Exception {
    final int numShardsToExpect = Integer.parseInt(Utils.DEFAULT_TOTAL_SHARDS);
    final String groupName = "testInboundDoubleHappyPathRegister";
    try (final RoutingStrategy.Inbound ib1 = new RoutingInboundManager().getAssociatedInstance(ClusterGroupInbound.class.getPackage().getName() + ":" + groupName);
        final RoutingStrategy.Inbound ib2 = new RoutingInboundManager().getAssociatedInstance(ClusterGroupInbound.class.getPackage().getName() + ":" + groupName)) {
        final ClusterId clusterId = new ClusterId("test", "test");
        final NodeAddress node1Addr = new DummyNodeAddress("node1");
        final GroupDetails gd1 = new GroupDetails(groupName, node1Addr);
        final ContainerAddress node1Ca = new ContainerAddress(node1Addr, 0);
        final Utils<GroupDetails> utils = new Utils<>(infra, groupName, gd1);
        ib1.setContainerDetails(clusterId, node1Ca, (l, m) -> {
        });
        ib1.start(infra);
        final NodeAddress node2Addr = new DummyNodeAddress("node2");
        final ContainerAddress node2Ca = new ContainerAddress(node2Addr, 0);
        ib2.setContainerDetails(clusterId, node2Ca, (l, m) -> {
        });
        try (final ClusterInfoSession session2 = sessFact.createSession()) {
            ib2.start(new TestInfrastructure(session2, infra.getScheduler()));
            assertTrue(waitForShards(session, utils, numShardsToExpect));
            // if this worked right then numShardsToExpect/2 should be owned by each ... eventually.
            checkForShardDistribution(session, utils, numShardsToExpect, 2);
            // disrupt the session. This should cause a reshuffle but not fail
            disruptor.accept(session2);
            // everything should settle back
            checkForShardDistribution(session, utils, numShardsToExpect, 2);
            // now kill the second session.
            // this will disconnect the second Inbound and so the first should take over
            session2.close();
            // see if we now have 1 session and it has all shards
            checkForShardDistribution(session, utils, numShardsToExpect, 1);
        }
    }
}
Also used : TestInfrastructure(net.dempsy.util.TestInfrastructure) ClusterId(net.dempsy.config.ClusterId) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) RoutingInboundManager(net.dempsy.router.RoutingInboundManager) GroupDetails(net.dempsy.router.group.intern.GroupDetails) Utils(net.dempsy.router.shardutils.Utils) RoutingStrategy(net.dempsy.router.RoutingStrategy) NodeAddress(net.dempsy.transport.NodeAddress) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) Test(org.junit.Test)

Example 3 with ContainerAddress

use of net.dempsy.router.RoutingStrategy.ContainerAddress 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));
            }
        }
    }
}
Also used : ShardAssignment(net.dempsy.router.shardutils.Utils.ShardAssignment) Arrays(java.util.Arrays) ClusterInfoException(net.dempsy.cluster.ClusterInfoException) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) NodeAddress(net.dempsy.transport.NodeAddress) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) Utils(net.dempsy.router.shardutils.Utils) Supplier(java.util.function.Supplier) RoutingStrategyManager(net.dempsy.router.RoutingStrategyManager) HashSet(java.util.HashSet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RoutingStrategy(net.dempsy.router.RoutingStrategy) Map(java.util.Map) Manager(net.dempsy.Manager) TestInfrastructure(net.dempsy.util.TestInfrastructure) RoutingInboundManager(net.dempsy.router.RoutingInboundManager) ClusterId(net.dempsy.config.ClusterId) Logger(org.slf4j.Logger) Assert.assertNotNull(org.junit.Assert.assertNotNull) ClusterInfoSessionFactory(net.dempsy.cluster.ClusterInfoSessionFactory) Assert.assertTrue(org.junit.Assert.assertTrue) Set(java.util.Set) GroupDetails(net.dempsy.router.group.intern.GroupDetails) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Consumer(java.util.function.Consumer) List(java.util.List) ConditionPoll.poll(net.dempsy.utils.test.ConditionPoll.poll) Infrastructure(net.dempsy.Infrastructure) Functional.chain(net.dempsy.util.Functional.chain) BaseRouterTestWithSession(net.dempsy.router.BaseRouterTestWithSession) Assert.assertEquals(org.junit.Assert.assertEquals) RoutingStrategyManager(net.dempsy.router.RoutingStrategyManager) ClusterId(net.dempsy.config.ClusterId) HashMap(java.util.HashMap) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) RoutingInboundManager(net.dempsy.router.RoutingInboundManager) GroupDetails(net.dempsy.router.group.intern.GroupDetails) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Utils(net.dempsy.router.shardutils.Utils) RoutingStrategy(net.dempsy.router.RoutingStrategy) TestInfrastructure(net.dempsy.util.TestInfrastructure) Infrastructure(net.dempsy.Infrastructure) NodeAddress(net.dempsy.transport.NodeAddress) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) Test(org.junit.Test)

Example 4 with ContainerAddress

use of net.dempsy.router.RoutingStrategy.ContainerAddress in project Dempsy by Dempsy.

the class TestLeaderAndSubscriber method testOneLeader.

@Test
public void testOneLeader() throws InterruptedException {
    final ClusterId cid = setTestName("testOneLeader");
    final Utils<ContainerAddress> utils = new Utils<ContainerAddress>(makeInfra(session, sched), cid.clusterName, new ContainerAddress(new DummyNodeAddress(), new int[] { 0 }));
    final AtomicBoolean isRunning = new AtomicBoolean(true);
    try {
        final Leader<ContainerAddress> l = new Leader<ContainerAddress>(utils, 256, 1, infra, isRunning, ContainerAddress[]::new);
        l.process();
        assertTrue(poll(o -> l.imIt()));
    } finally {
        isRunning.set(false);
    }
}
Also used : Logger(org.slf4j.Logger) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) ClusterInfoSessionFactory(net.dempsy.cluster.ClusterInfoSessionFactory) NodeAddress(net.dempsy.transport.NodeAddress) LoggerFactory(org.slf4j.LoggerFactory) Assert.assertTrue(org.junit.Assert.assertTrue) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Test(org.junit.Test) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) ConditionPoll.poll(net.dempsy.utils.test.ConditionPoll.poll) BaseRouterTestWithSession(net.dempsy.router.BaseRouterTestWithSession) Assert.assertEquals(org.junit.Assert.assertEquals) ClusterId(net.dempsy.config.ClusterId) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClusterId(net.dempsy.config.ClusterId) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) Test(org.junit.Test)

Example 5 with ContainerAddress

use of net.dempsy.router.RoutingStrategy.ContainerAddress in project Dempsy by Dempsy.

the class TestLeaderAndSubscriber method testLeaderWithMutipleSubscribers.

@Test
public void testLeaderWithMutipleSubscribers() throws Exception {
    final int NUM_SUBS = 10;
    final ClusterId cid = setTestName("testLeaderWithMutipleSubscribers");
    final AtomicBoolean isRunning = new AtomicBoolean(true);
    final List<Thread> threads = new ArrayList<>();
    try {
        final List<Subscriber<ContainerAddress>> subs = new ArrayList<>();
        final AtomicBoolean go = new AtomicBoolean(false);
        for (int i = 0; i < NUM_SUBS; i++) {
            final Utils<ContainerAddress> utils = new Utils<>(makeInfra(session, sched), cid.clusterName, new ContainerAddress(new DummyNodeAddress(), new int[] { 0 }));
            final Subscriber<ContainerAddress> s;
            subs.add(s = new Subscriber<>(utils, infra, isRunning, (l, m) -> {
            }, 256));
            final Thread t = new Thread(() -> {
                // wait for it.
                while (!go.get()) {
                    if (!isRunning.get())
                        return;
                    Thread.yield();
                }
                s.process();
            }, "testLeaderWithMutipleSubscribers-" + i);
            t.start();
            threads.add(t);
        }
        go.set(true);
        final Utils<ContainerAddress> utils = new Utils<>(makeInfra(session, sched), cid.clusterName, subs.get(3).getUtils().thisNodeAddress);
        final Leader<ContainerAddress> l = new Leader<>(utils, 256, 1, infra, isRunning, ContainerAddress[]::new);
        l.process();
        assertTrue(poll(o -> l.imIt()));
        // wait until ready
        assertTrue(poll(o -> subs.stream().filter(s -> s.isReady()).count() == NUM_SUBS));
        final int lowerNum = Math.floorDiv(256, NUM_SUBS);
        final int upperNum = (int) Math.ceil((double) 256 / NUM_SUBS);
        // do we have balanced subs?
        assertTrue(poll(o -> subs.stream().filter(s -> s.numShardsIOwn() >= lowerNum).filter(s -> s.numShardsIOwn() <= upperNum).count() == NUM_SUBS));
        isRunning.set(false);
        assertTrue(poll(o -> threads.stream().filter(t -> t.isAlive()).count() == 0));
    } finally {
        isRunning.set(false);
    }
}
Also used : Logger(org.slf4j.Logger) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) ClusterInfoSessionFactory(net.dempsy.cluster.ClusterInfoSessionFactory) NodeAddress(net.dempsy.transport.NodeAddress) LoggerFactory(org.slf4j.LoggerFactory) Assert.assertTrue(org.junit.Assert.assertTrue) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Test(org.junit.Test) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) ConditionPoll.poll(net.dempsy.utils.test.ConditionPoll.poll) BaseRouterTestWithSession(net.dempsy.router.BaseRouterTestWithSession) Assert.assertEquals(org.junit.Assert.assertEquals) ClusterId(net.dempsy.config.ClusterId) ClusterId(net.dempsy.config.ClusterId) ArrayList(java.util.ArrayList) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Test(org.junit.Test)

Aggregations

ContainerAddress (net.dempsy.router.RoutingStrategy.ContainerAddress)21 ClusterId (net.dempsy.config.ClusterId)16 RoutingStrategy (net.dempsy.router.RoutingStrategy)15 Test (org.junit.Test)15 NodeAddress (net.dempsy.transport.NodeAddress)13 ClusterInfoSession (net.dempsy.cluster.ClusterInfoSession)10 RoutingStrategyManager (net.dempsy.router.RoutingStrategyManager)8 Utils (net.dempsy.router.shardutils.Utils)8 List (java.util.List)7 Manager (net.dempsy.Manager)7 ClusterInfoSessionFactory (net.dempsy.cluster.ClusterInfoSessionFactory)7 TestInfrastructure (net.dempsy.util.TestInfrastructure)7 ConditionPoll.poll (net.dempsy.utils.test.ConditionPoll.poll)7 Assert.assertEquals (org.junit.Assert.assertEquals)7 Assert.assertTrue (org.junit.Assert.assertTrue)7 Logger (org.slf4j.Logger)7 LoggerFactory (org.slf4j.LoggerFactory)7 HashMap (java.util.HashMap)6 Map (java.util.Map)6 Consumer (java.util.function.Consumer)6