Search in sources :

Example 1 with Container

use of net.dempsy.container.Container in project Dempsy by Dempsy.

the class TestThreadingModel method test.

@Test
public void test() throws Exception {
    try (final ThreadingModel qctm = ut) {
        final Object waitOnMe = new Object();
        final AtomicLong numPending = new AtomicLong(0L);
        final AtomicLong sequence = new AtomicLong(0L);
        final AtomicLong numRejected = new AtomicLong(0L);
        final AtomicLong numCompleted = new AtomicLong(0L);
        final AtomicLong numCompletedSuccessfully = new AtomicLong(0L);
        int totalNumSubmitted = 0;
        // submit 1 to busy every worker
        for (int i = 0; i < numThreads; i++) {
            submitOne(ut, waitOnMe, sequence, numPending, numRejected, numCompleted, numCompletedSuccessfully);
            totalNumSubmitted++;
        }
        assertTrue(poll(o -> numPending.get() >= numThreads));
        // submit 1 for every spot in the queue
        for (int i = 0; i < maxNumLimited; i++) {
            submitOne(ut, waitOnMe, sequence, numPending, numRejected, numCompleted, numCompletedSuccessfully);
            totalNumSubmitted++;
        }
        Thread.sleep(10);
        assertEquals(numThreads, numPending.get());
        assertEquals(maxNumLimited, ut.getNumberLimitedPending());
        // double the pending
        for (int i = 0; i < maxNumLimited; i++) {
            submitOne(ut, waitOnMe, sequence, numPending, numRejected, numCompleted, numCompletedSuccessfully);
            totalNumSubmitted++;
        }
        assertEquals(maxNumLimited * 2, ut.getNumberLimitedPending());
        submitOne(ut, waitOnMe, sequence, numPending, numRejected, numCompleted, numCompletedSuccessfully);
        totalNumSubmitted++;
        assertTrue(poll(o -> numRejected.get() == 1));
        Thread.sleep(10);
        assertTrue(poll(o -> numRejected.get() == 1));
        assertEquals(numThreads, numPending.get());
        assertEquals(maxNumLimited * 2, ut.getNumberLimitedPending());
        // now let one complete.
        synchronized (waitOnMe) {
            waitOnMe.notify();
        }
        // after letting one go, several things will happen.
        // First, all of the ones greater than the max allowed
        // will be rejected since there's now a thread free to
        // do the rejecting. This means there will be 1 complete
        // and maxNumLimited - 1 rejected.
        // 
        // Because we DON'T "vent at the container" the following
        // one will execute and wait on the condition. This means
        // we should end up with 1 completed successfully and all
        // threads pending again.
        assertTrue(poll(o -> numCompletedSuccessfully.get() == 1));
        assertTrue(poll(o -> ut.getNumberLimitedPending() <= maxNumLimited));
        Thread.sleep(10);
        assertEquals(1, numCompletedSuccessfully.get());
        assertEquals(numThreads, numPending.get());
        System.out.println("===================================");
        System.out.println("total messages submitted:" + totalNumSubmitted);
        System.out.println("total messages in execution:" + numPending);
        System.out.println("total messages successfully:" + numCompletedSuccessfully);
        System.out.println("total messages rejected:" + numRejected);
        System.out.println("total messages in waiting:" + ut.getNumberLimitedPending());
        assertEquals(maxNumLimited, ut.getNumberLimitedPending());
        // now if we let them all go, the rest should execute.
        synchronized (waitOnMe) {
            waitOnSignal = false;
            waitOnMe.notifyAll();
        }
        assertTrue(poll(totalNumSubmitted, t -> t - numRejected.get() == numCompletedSuccessfully.get()));
        Thread.sleep(200);
        assertEquals(totalNumSubmitted - numRejected.get(), numCompletedSuccessfully.get());
        System.out.println("===================================");
        System.out.println("total messages submitted:" + totalNumSubmitted);
        System.out.println("total messages in execution:" + numPending);
        System.out.println("total messages successfully:" + numCompletedSuccessfully);
        System.out.println("total messages rejected:" + numRejected);
        System.out.println("total messages in waiting:" + ut.getNumberLimitedPending());
        // and finally, are they all accounted for
        assertEquals(totalNumSubmitted, numCompleted.get());
    }
}
Also used : RunWith(org.junit.runner.RunWith) Parameters(org.junit.runners.Parameterized.Parameters) DummyContainer(net.dempsy.container.DummyContainer) Assert.assertTrue(org.junit.Assert.assertTrue) MessageDeliveryJob(net.dempsy.container.MessageDeliveryJob) Test(org.junit.Test) ContainerJob(net.dempsy.container.ContainerJob) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) ContainerJobMetadata(net.dempsy.container.ContainerJobMetadata) Functional.ignore(net.dempsy.util.Functional.ignore) ConditionPoll.poll(net.dempsy.utils.test.ConditionPoll.poll) Functional.chain(net.dempsy.util.Functional.chain) Container(net.dempsy.container.Container) Assert.assertEquals(org.junit.Assert.assertEquals) Parameterized(org.junit.runners.Parameterized) AtomicLong(java.util.concurrent.atomic.AtomicLong) Test(org.junit.Test)

Example 2 with Container

use of net.dempsy.container.Container in project Dempsy by Dempsy.

the class TestInstanceManager method testOutputCountsOkay.

@Test
public void testOutputCountsOkay() throws Exception {
    final OutputTestMP prototype = new OutputTestMP();
    try (final Container manager = setupContainer(new MessageProcessor<OutputTestMP>(prototype))) {
        final DummyDispatcher dispatcher = ((DummyDispatcher) manager.getDispatcher());
        // we need to dispatch messages to create MP instances
        final KeyedMessageWithType message1 = km(new MessageOne(1));
        final KeyedMessageWithType message2 = km(new MessageOne(2));
        manager.dispatch(message1, Operation.handle, true);
        manager.dispatch(message2, Operation.handle, true);
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
        manager.invokeOutput();
        assertEquals("number of processed messages should include outputs.", 4, ((ClusterMetricGetters) statsCollector).getProcessedMessageCount());
    }
}
Also used : NonLockingAltContainer(net.dempsy.container.altnonlocking.NonLockingAltContainer) Container(net.dempsy.container.Container) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 3 with Container

use of net.dempsy.container.Container in project Dempsy by Dempsy.

the class TestOutputSchedulers method testCronScheduleWithConcurrencySetting.

/**
 * Test cron schedule with concurrency setting
 *
 * @throws Exception the exception
 */
@Test
public void testCronScheduleWithConcurrencySetting() throws Exception {
    try (final CronOutputSchedule cronOutputSchedule = new CronOutputSchedule("0/1 * * * * ?")) {
        cronOutputSchedule.setOutputInvoker(container);
        cronOutputSchedule.start(new TestInfrastructure(null));
        Thread.sleep(1000);
        assertTrue(poll(outputInvoked, oi -> oi.get()));
    }
}
Also used : TimeUnit(java.util.concurrent.TimeUnit) NonLockingAltContainer(net.dempsy.container.altnonlocking.NonLockingAltContainer) ConditionPoll.poll(net.dempsy.utils.test.ConditionPoll.poll) TestInfrastructure(net.dempsy.util.TestInfrastructure) Assert.assertTrue(org.junit.Assert.assertTrue) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Container(net.dempsy.container.Container) Test(org.junit.Test) Before(org.junit.Before) TestInfrastructure(net.dempsy.util.TestInfrastructure) Test(org.junit.Test)

Example 4 with Container

use of net.dempsy.container.Container in project Dempsy by Dempsy.

the class TestInstanceManager method testOutputShortCircuitsIfNoOutputMethod.

@Test
public void testOutputShortCircuitsIfNoOutputMethod() throws Exception {
    final CombinedMP prototype = new CombinedMP();
    final Container manager = setupContainer(new MessageProcessor<CombinedMP>(prototype));
    final DummyDispatcher dispatcher = ((DummyDispatcher) manager.getDispatcher());
    // we need to dispatch messages to create MP instances
    final KeyedMessageWithType message1 = km(new MessageOne(1));
    final KeyedMessageWithType message2 = km(new MessageOne(2));
    manager.dispatch(message1, Operation.handle, true);
    manager.dispatch(message2, Operation.handle, true);
    assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
    manager.invokeOutput();
    // output messages are NOT considered "processed" if there is no output method on the MP.
    assertEquals("number of processed messages should include outputs.", 2, ((ClusterMetricGetters) statsCollector).getProcessedMessageCount());
}
Also used : Container(net.dempsy.container.Container) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 5 with Container

use of net.dempsy.container.Container in project Dempsy by Dempsy.

the class NodeManager method start.

public NodeManager start() throws DempsyException {
    validate();
    nodeStatsCollector = tr.track((NodeStatsCollector) node.getNodeStatsCollector());
    // TODO: cleaner?
    statsCollectorFactory = tr.track(new Manager<>(ClusterStatsCollectorFactory.class).getAssociatedInstance(node.getClusterStatsCollectorFactoryId()));
    // =====================================
    // set the dispatcher on adaptors and create containers for mp clusters
    final AtomicReference<String> firstAdaptorClusterName = new AtomicReference<>(null);
    node.getClusters().forEach(c -> {
        if (c.isAdaptor()) {
            if (firstAdaptorClusterName.get() == null)
                firstAdaptorClusterName.set(c.getClusterId().clusterName);
            final Adaptor adaptor = c.getAdaptor();
            adaptors.put(c.getClusterId(), adaptor);
            if (c.getRoutingStrategyId() != null && !"".equals(c.getRoutingStrategyId().trim()) && !" ".equals(c.getRoutingStrategyId().trim()))
                LOGGER.warn("The cluster " + c.getClusterId() + " contains an adaptor but also has the routingStrategy set. The routingStrategy will be ignored.");
            if (c.getOutputScheduler() != null)
                LOGGER.warn("The cluster " + c.getClusterId() + " contains an adaptor but also has an output executor set. The output executor will never be used.");
        } else {
            String containerTypeId = c.getContainerTypeId();
            if (containerTypeId == null)
                // can't be null
                containerTypeId = node.getContainerTypeId();
            final Container con = makeContainer(containerTypeId).setMessageProcessor(c.getMessageProcessor()).setClusterId(c.getClusterId()).setMaxPendingMessagesPerContainer(c.getMaxPendingMessagesPerContainer());
            // TODO: This is a hack for now.
            final Manager<RoutingStrategy.Inbound> inboundManager = new RoutingInboundManager();
            final RoutingStrategy.Inbound is = inboundManager.getAssociatedInstance(c.getRoutingStrategyId());
            final boolean outputSupported = c.getMessageProcessor().isOutputSupported();
            final Object outputScheduler = c.getOutputScheduler();
            // if there mp handles output but there's no output scheduler then we should warn.
            if (outputSupported && outputScheduler == null)
                LOGGER.warn("The cluster " + c.getClusterId() + " contains a message processor that supports an output cycle but there's no executor set so it will never be invoked.");
            if (!outputSupported && outputScheduler != null)
                LOGGER.warn("The cluster " + c.getClusterId() + " contains a message processor that doesn't support an output cycle but there's an output cycle executor set. The output cycle executor will never be used.");
            final OutputScheduler os = (outputSupported && outputScheduler != null) ? (OutputScheduler) outputScheduler : null;
            containers.add(new PerContainer(con, is, c, os));
        }
    });
    // it we're all adaptor then don't bother to get the receiver.
    if (containers.size() == 0) {
        // here there's no point in a receiver since there's nothing to receive.
        if (firstAdaptorClusterName.get() == null)
            throw new IllegalStateException("There seems to be no clusters or adaptors defined for this node \"" + node.toString() + "\"");
    } else {
        receiver = (Receiver) node.getReceiver();
        if (// otherwise we're all adaptor
        receiver != null)
            nodeAddress = receiver.getAddress(this);
        else if (firstAdaptorClusterName.get() == null)
            throw new IllegalStateException("There seems to be no clusters or adaptors defined for this node \"" + node.toString() + "\"");
    }
    nodeId = Optional.ofNullable(nodeAddress).map(n -> n.getGuid()).orElse(firstAdaptorClusterName.get());
    if (nodeStatsCollector == null) {
        LOGGER.warn("There is no {} set for the the application '{}'", StatsCollector.class.getSimpleName(), node.application);
        nodeStatsCollector = new DummyNodeStatsCollector();
    }
    nodeStatsCollector.setNodeId(nodeId);
    if (nodeAddress == null && node.getReceiver() != null)
        LOGGER.warn("The node at " + nodeId + " contains no message processors but has a Reciever set. The receiver will never be started.");
    if (nodeAddress == null && node.getDefaultRoutingStrategyId() != null)
        LOGGER.warn("The node at " + nodeId + " contains no message processors but has a defaultRoutingStrategyId set. The routingStrategyId will never be used.");
    if (threading == null)
        threading = tr.track(new DefaultThreadingModel(nodeId)).configure(node.getConfiguration()).start(nodeId);
    else if (!threading.isStarted())
        threading.start(nodeId);
    nodeStatsCollector.setMessagesPendingGauge(() -> threading.getNumberLimitedPending());
    final NodeReceiver nodeReciever = receiver == null ? null : tr.track(new NodeReceiver(containers.stream().map(pc -> pc.container).collect(Collectors.toList()), threading, nodeStatsCollector));
    final Map<ClusterId, ClusterInformation> messageTypesByClusterId = new HashMap<>();
    containers.stream().map(pc -> pc.clusterDefinition).forEach(c -> {
        messageTypesByClusterId.put(c.getClusterId(), new ClusterInformation(c.getRoutingStrategyId(), c.getClusterId(), c.getMessageProcessor().messagesTypesHandled()));
    });
    final NodeInformation nodeInfo = nodeAddress != null ? new NodeInformation(receiver.transportTypeId(), nodeAddress, messageTypesByClusterId) : null;
    // Then actually register the Node
    if (nodeInfo != null) {
        keepNodeRegstered = new PersistentTask(LOGGER, isRunning, persistenceScheduler, RETRY_PERIOND_MILLIS) {

            @Override
            public boolean execute() {
                try {
                    session.recursiveMkdir(rootPaths.clustersDir, null, DirMode.PERSISTENT, DirMode.PERSISTENT);
                    session.recursiveMkdir(rootPaths.nodesDir, null, DirMode.PERSISTENT, DirMode.PERSISTENT);
                    final String nodePath = rootPaths.nodesDir + "/" + nodeId;
                    session.mkdir(nodePath, nodeInfo, DirMode.EPHEMERAL);
                    final NodeInformation reread = (NodeInformation) session.getData(nodePath, this);
                    final boolean ret = nodeInfo.equals(reread);
                    if (ret == true)
                        ptaskReady.set(true);
                    return ret;
                } catch (final ClusterInfoException e) {
                    final String logmessage = "Failed to register the node. Retrying in " + RETRY_PERIOND_MILLIS + " milliseconds.";
                    if (LOGGER.isDebugEnabled())
                        LOGGER.info(logmessage, e);
                    else
                        LOGGER.info(logmessage, e);
                }
                return false;
            }

            @Override
            public String toString() {
                return "register node information";
            }
        };
    }
    // =====================================
    // The layering works this way.
    // 
    // Receiver -> NodeReceiver -> adaptor -> container -> OutgoingDispatcher -> RoutingStrategyOB -> Transport
    // 
    // starting needs to happen in reverse.
    // =====================================
    isRunning.set(true);
    this.tManager = tr.start(new TransportManager(), this);
    this.rsManager = tr.start(new RoutingStrategyManager(), this);
    // create the router but don't start it yet.
    this.router = new OutgoingDispatcher(rsManager, nodeAddress, nodeId, nodeReciever, tManager, nodeStatsCollector);
    // set up containers
    containers.forEach(pc -> pc.container.setDispatcher(router).setEvictionCycle(pc.clusterDefinition.getEvictionFrequency().evictionFrequency, pc.clusterDefinition.getEvictionFrequency().evictionTimeUnit));
    // IB routing strategy
    final int numContainers = containers.size();
    for (int i = 0; i < numContainers; i++) {
        final PerContainer c = containers.get(i);
        c.inboundStrategy.setContainerDetails(c.clusterDefinition.getClusterId(), new ContainerAddress(nodeAddress, i), c.container);
    }
    // setup the output executors by passing the containers
    containers.stream().filter(pc -> pc.outputScheduler != null).forEach(pc -> pc.outputScheduler.setOutputInvoker(pc.container));
    // set up adaptors
    adaptors.values().forEach(a -> a.setDispatcher(router));
    // start containers after setting inbound
    containers.forEach(pc -> tr.start(pc.container.setInbound(pc.inboundStrategy), this));
    // start the output schedulers now that the containers have been started.
    containers.stream().map(pc -> pc.outputScheduler).filter(os -> os != null).forEach(os -> tr.start(os, this));
    // start IB routing strategy
    containers.forEach(pc -> tr.start(pc.inboundStrategy, this));
    // start router
    tr.start(this.router, this);
    final PersistentTask startAdaptorAfterRouterIsRunning = new PersistentTask(LOGGER, isRunning, this.persistenceScheduler, 500) {

        @Override
        public boolean execute() {
            if (!router.isReady())
                return false;
            adaptors.entrySet().forEach(e -> threading.runDaemon(() -> tr.track(e.getValue()).start(), "Adaptor-" + e.getKey().clusterName));
            return true;
        }
    };
    // make sure the router is running. Once it is, start the adaptor(s)
    startAdaptorAfterRouterIsRunning.process();
    if (receiver != null)
        tr.track(receiver).start(nodeReciever, this);
    // close this session when we're done.
    tr.track(session);
    // make it known we're here and ready
    if (keepNodeRegstered != null)
        keepNodeRegstered.process();
    else
        ptaskReady.set(true);
    return this;
}
Also used : Adaptor(net.dempsy.messages.Adaptor) ClusterInfoException(net.dempsy.cluster.ClusterInfoException) TransportManager(net.dempsy.transport.TransportManager) ClusterInfoSession(net.dempsy.cluster.ClusterInfoSession) Node(net.dempsy.config.Node) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) DefaultThreadingModel(net.dempsy.threading.DefaultThreadingModel) NodeAddress(net.dempsy.transport.NodeAddress) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) DirMode(net.dempsy.cluster.DirMode) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) OutputScheduler(net.dempsy.output.OutputScheduler) RoutingStrategyManager(net.dempsy.router.RoutingStrategyManager) Functional.ignore(net.dempsy.util.Functional.ignore) RoutingStrategy(net.dempsy.router.RoutingStrategy) Map(java.util.Map) ThreadingModel(net.dempsy.threading.ThreadingModel) RoutingInboundManager(net.dempsy.router.RoutingInboundManager) Receiver(net.dempsy.transport.Receiver) ClusterId(net.dempsy.config.ClusterId) StatsCollector(net.dempsy.monitoring.StatsCollector) Cluster(net.dempsy.config.Cluster) ClusterStatsCollectorFactory(net.dempsy.monitoring.ClusterStatsCollectorFactory) DummyNodeStatsCollector(net.dempsy.monitoring.dummy.DummyNodeStatsCollector) Logger(org.slf4j.Logger) SafeString(net.dempsy.util.SafeString) ClusterInfoSessionFactory(net.dempsy.cluster.ClusterInfoSessionFactory) Collection(java.util.Collection) OutgoingDispatcher(net.dempsy.intern.OutgoingDispatcher) Collectors(java.util.stream.Collectors) AutoDisposeSingleThreadScheduler(net.dempsy.util.executor.AutoDisposeSingleThreadScheduler) TimeUnit(java.util.concurrent.TimeUnit) ClusterStatsCollector(net.dempsy.monitoring.ClusterStatsCollector) NodeStatsCollector(net.dempsy.monitoring.NodeStatsCollector) List(java.util.List) Adaptor(net.dempsy.messages.Adaptor) PersistentTask(net.dempsy.utils.PersistentTask) Optional(java.util.Optional) Container(net.dempsy.container.Container) Inbound(net.dempsy.router.RoutingStrategy.Inbound) MessageProcessorLifecycle(net.dempsy.messages.MessageProcessorLifecycle) Collections(java.util.Collections) RoutingStrategyManager(net.dempsy.router.RoutingStrategyManager) HashMap(java.util.HashMap) OutgoingDispatcher(net.dempsy.intern.OutgoingDispatcher) ClusterInfoException(net.dempsy.cluster.ClusterInfoException) SafeString(net.dempsy.util.SafeString) Inbound(net.dempsy.router.RoutingStrategy.Inbound) PersistentTask(net.dempsy.utils.PersistentTask) OutputScheduler(net.dempsy.output.OutputScheduler) RoutingInboundManager(net.dempsy.router.RoutingInboundManager) Container(net.dempsy.container.Container) DummyNodeStatsCollector(net.dempsy.monitoring.dummy.DummyNodeStatsCollector) RoutingStrategy(net.dempsy.router.RoutingStrategy) DummyNodeStatsCollector(net.dempsy.monitoring.dummy.DummyNodeStatsCollector) NodeStatsCollector(net.dempsy.monitoring.NodeStatsCollector) StatsCollector(net.dempsy.monitoring.StatsCollector) DummyNodeStatsCollector(net.dempsy.monitoring.dummy.DummyNodeStatsCollector) ClusterStatsCollector(net.dempsy.monitoring.ClusterStatsCollector) NodeStatsCollector(net.dempsy.monitoring.NodeStatsCollector) ClusterId(net.dempsy.config.ClusterId) AtomicReference(java.util.concurrent.atomic.AtomicReference) Inbound(net.dempsy.router.RoutingStrategy.Inbound) DefaultThreadingModel(net.dempsy.threading.DefaultThreadingModel) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) ClusterStatsCollectorFactory(net.dempsy.monitoring.ClusterStatsCollectorFactory) TransportManager(net.dempsy.transport.TransportManager)

Aggregations

Container (net.dempsy.container.Container)12 Test (org.junit.Test)11 NonLockingAltContainer (net.dempsy.container.altnonlocking.NonLockingAltContainer)8 TimeUnit (java.util.concurrent.TimeUnit)6 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)6 Assert.assertTrue (org.junit.Assert.assertTrue)6 ConditionPoll.poll (net.dempsy.utils.test.ConditionPoll.poll)5 KeyedMessageWithType (net.dempsy.messages.KeyedMessageWithType)4 TestInfrastructure (net.dempsy.util.TestInfrastructure)4 Before (org.junit.Before)4 List (java.util.List)3 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 AtomicLong (java.util.concurrent.atomic.AtomicLong)2 Collectors (java.util.stream.Collectors)2 Node (net.dempsy.config.Node)2 Adaptor (net.dempsy.messages.Adaptor)2 DefaultThreadingModel (net.dempsy.threading.DefaultThreadingModel)2 NodeAddress (net.dempsy.transport.NodeAddress)2 Receiver (net.dempsy.transport.Receiver)2