Search in sources :

Example 1 with ClusterInfoSession

use of net.dempsy.cluster.ClusterInfoSession in project Dempsy by Dempsy.

the class OutgoingDispatcher method start.

@Override
public void start(final Infrastructure infra) {
    final ClusterInfoSession session = infra.getCollaborator();
    final String nodesDir = infra.getRootPaths().nodesDir;
    checkup = new PersistentTask(LOGGER, isRunning, infra.getScheduler(), RETRY_TIMEOUT) {

        @Override
        public boolean execute() {
            try {
                // collect up all NodeInfo's known about.
                session.recursiveMkdir(nodesDir, null, DirMode.PERSISTENT, DirMode.PERSISTENT);
                final Collection<String> nodeDirs = session.getSubdirs(nodesDir, this);
                final Set<NodeInformation> alreadySeen = new HashSet<>();
                // get all of the subdirectories NodeInformations
                for (final String subdir : nodeDirs) {
                    final NodeInformation ni = (NodeInformation) session.getData(nodesDir + "/" + subdir, null);
                    if (ni == null) {
                        LOGGER.warn("A node directory was empty at " + subdir);
                        return false;
                    }
                    // see if node info is dupped.
                    if (alreadySeen.contains(ni)) {
                        LOGGER.warn("The node " + ni.nodeAddress + " seems to be registed more than once.");
                        continue;
                    }
                    if (ni.clusterInfoByClusterId.size() == 0) {
                        // it's ALL adaptor so there's no sense in dealing with it
                        LOGGER.trace("NodeInformation {} appears to be only an Adaptor.", ni);
                        continue;
                    }
                    alreadySeen.add(ni);
                }
                // check to see if there's new nodes.
                final ApplicationState.Update ud = outbounds.get().update(alreadySeen, thisNode, thisNodeId);
                if (!ud.change()) {
                    isReady.set(true);
                    // nothing to update.
                    return true;
                } else if (LOGGER.isTraceEnabled())
                    LOGGER.trace("Updating for " + thisNodeId);
                // otherwise we will be making changes so remove the current ApplicationState
                // this can cause instability.
                final ApplicationState obs = outbounds.getAndSet(null);
                try {
                    final ApplicationState newState = obs.apply(ud, tmanager, statsCollector, manager);
                    outbounds.set(newState);
                    isReady.set(true);
                    return true;
                } catch (final RuntimeException rte) {
                    // if we threw an exception after clearing the outbounds we need to restore it.
                    // This is likely a configuration error so we should probably warn about it.
                    LOGGER.warn("Unexpected exception while applying a topology update", rte);
                    outbounds.set(obs);
                    throw rte;
                }
            } catch (final ClusterInfoException e) {
                final String message = "Failed to find outgoing route information. Will retry shortly.";
                if (LOGGER.isTraceEnabled())
                    LOGGER.debug(message, e);
                else
                    LOGGER.debug(message);
                return false;
            }
        }

        @Override
        public String toString() {
            return "find nodes to route to";
        }
    };
    outbounds.set(new ApplicationState(tmanager, thisNode));
    isRunning.set(true);
    checkup.process();
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) ApplicationState(net.dempsy.intern.ApplicationState) ClusterInfoException(net.dempsy.cluster.ClusterInfoException) Collection(java.util.Collection) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) SafeString(net.dempsy.util.SafeString) PersistentTask(net.dempsy.utils.PersistentTask)

Example 2 with ClusterInfoSession

use of net.dempsy.cluster.ClusterInfoSession in project Dempsy by Dempsy.

the class TestManagedRoutingStrategy method testInboundWithOutbound.

@Test
public void testInboundWithOutbound() throws Exception {
    final int numShardsToExpect = Integer.parseInt(Utils.DEFAULT_TOTAL_SHARDS);
    final Manager<RoutingStrategy.Inbound> manager = new Manager<>(RoutingStrategy.Inbound.class);
    try (final RoutingStrategy.Inbound ib = manager.getAssociatedInstance(ManagedInbound.class.getPackage().getName())) {
        final ClusterId cid = setTestName("testInboundWithOutbound");
        final ContainerAddress oca = new ContainerAddress(new DummyNodeAddress("here"), 0);
        final Infrastructure infra = makeInfra(session, sched);
        final Utils<ContainerAddress> msutils = new Utils<>(infra, cid.clusterName, oca);
        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(ManagedInbound.class.getPackage().getName())) {
            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();
            try (ClusterInfoSession ses3 = sessFact.createSession();
                RoutingStrategy.Inbound ib2 = manager.getAssociatedInstance(ManagedInbound.class.getPackage().getName())) {
                ib2.setContainerDetails(cid, ca, (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) 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) 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) RoutingStrategyManager(net.dempsy.router.RoutingStrategyManager) Manager(net.dempsy.Manager) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) 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) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) Test(org.junit.Test)

Example 3 with ClusterInfoSession

use of net.dempsy.cluster.ClusterInfoSession in project Dempsy by Dempsy.

the class TestManagedRoutingStrategy method testInboundDoubleHappyPathRegister.

@Test
public void testInboundDoubleHappyPathRegister() throws Exception {
    final int numShardsToExpect = Integer.parseInt(Utils.DEFAULT_TOTAL_SHARDS);
    try (final RoutingStrategy.Inbound ib1 = new Manager<>(RoutingStrategy.Inbound.class).getAssociatedInstance(ManagedInbound.class.getPackage().getName());
        final RoutingStrategy.Inbound ib2 = new Manager<>(RoutingStrategy.Inbound.class).getAssociatedInstance(ManagedInbound.class.getPackage().getName())) {
        final ClusterId clusterId = new ClusterId("test", "test");
        final ContainerAddress node1Ca = new ContainerAddress(new DummyNodeAddress("node1"), 0);
        final Utils<ContainerAddress> utils = new Utils<>(infra, clusterId.clusterName, node1Ca);
        ib1.setContainerDetails(clusterId, node1Ca, (l, m) -> {
        });
        ib1.start(infra);
        final ContainerAddress node2Ca = new ContainerAddress(new DummyNodeAddress("node2"), 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) Utils(net.dempsy.router.shardutils.Utils) RoutingStrategy(net.dempsy.router.RoutingStrategy) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) Test(org.junit.Test)

Example 4 with ClusterInfoSession

use of net.dempsy.cluster.ClusterInfoSession in project Dempsy by Dempsy.

the class TestElasticity method testNumberCountAddOneThenDrop.

@Test
public void testNumberCountAddOneThenDrop() throws Throwable {
    runCombos("testNumberCountAddOneThenDrop", (r, c, s, t, ser) -> isElasticRoutingStrategy(r), actxPath, ns -> {
        // keepGoing is for the separate thread that pumps messages into the system.
        final AtomicBoolean keepGoing = new AtomicBoolean(true);
        try {
            LOGGER.trace("==== <- Starting");
            final List<NodeManagerWithContext> nodes = new ArrayList<>(ns.nodes);
            // grab the adaptor from the 0'th cluster + the 0'th (only) node.
            final NumberProducer adaptor = nodes.get(0).ctx.getBean(NumberProducer.class);
            // grab access to the Dispatcher from the Adaptor
            final Dispatcher dispatcher = adaptor.dispatcher;
            // This is a Runnable that will pump messages to the dispatcher until keepGoing is
            // flipped to 'false.' It's stateless so it can be reused as needed.
            final AtomicInteger rankIndexToSend = new AtomicInteger(0);
            final Runnable sendMessages = () -> {
                // for an integer is the integer itself so we can get every shard by sending
                while (keepGoing.get()) {
                    for (int num = 0; num < 20; num++) {
                        final int number = num;
                        dispatcher.dispatch(uncheck(() -> ke.extract(new Number(number, rankIndexToSend.get()))));
                    }
                }
            };
            try (final ClusterInfoSession session = ns.sessionFactory.createSession()) {
                waitForEvenShardDistribution(session, "test-cluster1", 3, nodes);
                // Grab the one NumberRank Mp from the single Node in the third (0 base 2nd) cluster.
                final NumberRank rank = nodes.get(4).ctx.getBean(NumberRank.class);
                runACycle(keepGoing, rankIndexToSend.get(), rank, sendMessages);
                // now, bring online another instance.
                LOGGER.trace("==== starting a new one");
                nodes.add(makeNode(new String[] { "elasticity/mp-num-count.xml" }));
                waitForEvenShardDistribution(session, "test-cluster1", 4, nodes);
                // make sure everything still goes through
                runACycle(keepGoing, rankIndexToSend.incrementAndGet(), rank, sendMessages);
                // now kill a node.
                final NodeManagerWithContext nm = nodes.remove(2);
                LOGGER.trace("==== Stopping middle node servicing shards ");
                nm.manager.stop();
                waitForEvenShardDistribution(session, "test-cluster1", 3, nodes);
                LOGGER.trace("==== Stopped middle Dempsy");
                // make sure everything still goes through
                runACycle(keepGoing, rankIndexToSend.incrementAndGet(), rank, sendMessages);
            }
        } finally {
            keepGoing.set(false);
            LOGGER.trace("==== Exiting test.");
        }
    });
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ArrayList(java.util.ArrayList) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) Dispatcher(net.dempsy.messages.Dispatcher) Test(org.junit.Test)

Example 5 with ClusterInfoSession

use of net.dempsy.cluster.ClusterInfoSession 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)

Aggregations

ClusterInfoSession (net.dempsy.cluster.ClusterInfoSession)11 Test (org.junit.Test)10 ClusterId (net.dempsy.config.ClusterId)8 NodeAddress (net.dempsy.transport.NodeAddress)7 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)6 ContainerAddress (net.dempsy.router.RoutingStrategy.ContainerAddress)6 ConditionPoll.poll (net.dempsy.utils.test.ConditionPoll.poll)6 Assert.assertEquals (org.junit.Assert.assertEquals)6 Assert.assertTrue (org.junit.Assert.assertTrue)6 ArrayList (java.util.ArrayList)5 List (java.util.List)5 Set (java.util.Set)5 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 Functional.chain (net.dempsy.util.Functional.chain)5 Logger (org.slf4j.Logger)5 LoggerFactory (org.slf4j.LoggerFactory)5 Map (java.util.Map)4 Collectors (java.util.stream.Collectors)4 Dispatcher (net.dempsy.messages.Dispatcher)4 RoutingStrategy (net.dempsy.router.RoutingStrategy)4