Search in sources :

Example 6 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType 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 7 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class TestInstanceManager method testMultipleInstanceCreation.

@Test
public void testMultipleInstanceCreation() throws Exception {
    final CombinedMP prototype = new CombinedMP();
    try (final LockingContainer manager = setupContainer(new MessageProcessor<CombinedMP>(prototype))) {
        final DummyDispatcher dispatcher = ((DummyDispatcher) manager.getDispatcher());
        assertEquals("starts with no instances", 0, manager.getProcessorCount());
        final KeyedMessageWithType message1 = km(new MessageOne(123));
        final InstanceWrapper wrapper1 = manager.getInstanceForKey(message1.key, message1.message);
        manager.dispatch(message1, Operation.handle, true);
        final CombinedMP instance1 = (CombinedMP) wrapper1.getInstance();
        final KeyedMessageWithType message2 = km(new MessageOne(456));
        final InstanceWrapper wrapper2 = manager.getInstanceForKey(message2.key, message2.message);
        manager.dispatch(message2, Operation.handle, true);
        final CombinedMP instance2 = (CombinedMP) wrapper2.getInstance();
        assertEquals("instances were created", 2, manager.getProcessorCount());
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
        assertEquals("message count to instance1", 1, instance1.messages.size());
        assertEquals("message count to instance2", 1, instance2.messages.size());
        assertSame("message1 went to instance1", message1.message, instance1.messages.get(0));
        assertSame("message2 went to instance2", message2.message, instance2.messages.get(0));
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
    }
}
Also used : InstanceWrapper(net.dempsy.container.locking.LockingContainer.InstanceWrapper) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 8 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class TestInstanceManager method testSingleInstanceOneMessage.

@Test
public void testSingleInstanceOneMessage() throws Throwable {
    final CombinedMP prototype = new CombinedMP();
    try (final LockingContainer manager = setupContainer(new MessageProcessor<CombinedMP>(prototype))) {
        assertEquals("starts with no instances", 0, manager.getProcessorCount());
        final KeyedMessageWithType message = km(new MessageOne(123));
        final InstanceWrapper wrapper = manager.getInstanceForKey(message.key, message.message);
        assertEquals("instance was created", 1, manager.getProcessorCount());
        final CombinedMP instance = (CombinedMP) wrapper.getInstance();
        // activation is now inline with insantiation so it's active immediately
        // assertEquals("instance not already activated", 0, instance.activationCount);
        assertEquals("instance activated", 1, instance.activationCount);
        assertEquals("instance has no existing messages", -1, instance.firstMessageTime);
        // assertNull("instance has no message list", instance.messages);
        assertTrue("real activation time", instance.activationTime > 0);
        assertEquals("message count", 0, instance.messages.size());
        // dispatch the message
        // wrapper.run();
        manager.dispatch(message, Operation.handle, true);
        assertEquals("instance activated", 1, instance.activationCount);
        assertTrue("real activation time", instance.activationTime > 0);
        assertSame("instance received message", message.message, instance.messages.get(0));
        assertEquals("message count", 1, instance.messages.size());
        assertTrue("activated before first message", instance.activationTime < instance.firstMessageTime);
        // The return value cannot be routed.
        assertEquals(new ReturnString("MessageOne"), ((DummyDispatcher) manager.getDispatcher()).lastDispatched.message);
        assertEquals("prototype not activated", 0, prototype.activationCount);
        assertEquals("prototype did not receive messages", -1, prototype.firstMessageTime);
        assertNull("prototype has no message list", prototype.messages);
    }
}
Also used : InstanceWrapper(net.dempsy.container.locking.LockingContainer.InstanceWrapper) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 9 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class TestInstanceManager method testSingleInstanceTwoMessagesSameClassSeparateExecution.

@Test
public void testSingleInstanceTwoMessagesSameClassSeparateExecution() throws Exception {
    final CombinedMP prototype = new CombinedMP();
    try (final LockingContainer manager = setupContainer(new MessageProcessor<CombinedMP>(prototype))) {
        final DummyDispatcher dispatcher = ((DummyDispatcher) manager.getDispatcher());
        assertEquals("starts with no instances", 0, manager.getProcessorCount());
        final KeyedMessageWithType message1 = km(new MessageOne(123));
        final InstanceWrapper wrapper1 = manager.getInstanceForKey(message1.key, message1.message);
        manager.dispatch(message1, Operation.handle, true);
        final CombinedMP instance = (CombinedMP) wrapper1.getInstance();
        assertEquals("instance was created", 1, manager.getProcessorCount());
        assertEquals("instance activated", 1, instance.activationCount);
        assertTrue("real activation time", instance.activationTime > 0);
        assertSame("instance received message", message1.message, instance.messages.get(0));
        assertEquals("message count", 1, instance.messages.size());
        assertTrue("activated before first message", instance.activationTime < instance.firstMessageTime);
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
        final KeyedMessageWithType message2 = km(new MessageOne(123));
        final InstanceWrapper wrapper2 = manager.getInstanceForKey(message2.key, message2.message);
        manager.dispatch(message2, Operation.handle, true);
        assertSame("same wrapper returned for second message", wrapper1, wrapper2);
        assertEquals("no other instance was created", 1, manager.getProcessorCount());
        assertEquals("no second activation", 1, instance.activationCount);
        assertEquals("both messages delivered", 2, instance.messages.size());
        assertSame("message1 delivered first", message1.message, instance.messages.get(0));
        assertSame("message2 delivered second", message2.message, instance.messages.get(1));
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
    }
}
Also used : InstanceWrapper(net.dempsy.container.locking.LockingContainer.InstanceWrapper) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 10 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class OutgoingDispatcher method dispatch.

@Override
public void dispatch(final KeyedMessageWithType messageParam, final MessageResourceManager disposer) throws InterruptedException {
    final boolean traceEnabled = LOGGER.isTraceEnabled();
    if (messageParam == null)
        throw new NullPointerException("Attempt to dispatch a null message.");
    final Object messageKey = messageParam.key;
    if (messageKey == null)
        throw new NullPointerException("Message " + SafeString.objectDescription(messageParam) + " has a null key.");
    boolean messageSentSomewhere = false;
    try (ResourceManagerClosable x = new ResourceManagerClosable(disposer, messageParam)) {
        final KeyedMessageWithType message = x.toUse;
        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.", thisNodeId);
                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) {
                if (traceEnabled)
                    LOGGER.trace("[{}] No cluster that handles messages of type {}", thisNodeId, 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) {
                        if (LOGGER.isDebugEnabled())
                            LOGGER.debug("[{}] No way to send the message {} to specific cluster for the time being", thisNodeId, 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);
                    }
                }
            }
        }
        if (containerByNodeAddress.size() == 0) {
            if (traceEnabled)
                LOGGER.trace("[{}] There appears to be no valid destination addresses for the message {}", thisNodeId, SafeString.objectDescription(message.message));
        }
        for (final Map.Entry<NodeAddress, ContainerAddress> e : containerByNodeAddress.entrySet()) {
            final NodeAddress curNode = e.getKey();
            final ContainerAddress curAddr = e.getValue();
            // If we're local then just send this message directly back to our own node.
            if (curNode.equals(thisNode)) {
                if (traceEnabled)
                    LOGGER.trace("Sending local {}", message);
                // if the message is a resource then the disposer will be used to dispose of the message
                // but it needs an additional replicate. See propogateMessageToNode javadoc.
                nodeReciever.propogateMessageToNode(new RoutedMessage(curAddr.clusters, messageKey, disposer == null ? message.message : disposer.replicate(message.message)), // this shouldn't count since Router is an OUTGOING class
                false, disposer);
                messageSentSomewhere = true;
            } else {
                if (traceEnabled)
                    LOGGER.trace("Sending {} to {}", message, curNode);
                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(), thisNodeId);
                } else {
                    sender.send(new RoutedMessage(curAddr.clusters, messageKey, sender.considerMessageOwnsershipTransfered() ? (disposer == null ? message.message : disposer.replicate(message.message)) : message.message));
                    messageSentSomewhere = true;
                }
            }
        }
    } finally {
        if (!messageSentSomewhere) {
            if (traceEnabled)
                LOGGER.trace("Message not sent.");
            statsCollector.messageNotSent();
        }
    }
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) RoutedMessage(net.dempsy.transport.RoutedMessage) SafeString(net.dempsy.util.SafeString) ContainerAddress(net.dempsy.router.RoutingStrategy.ContainerAddress) Sender(net.dempsy.transport.Sender) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) RoutingStrategy(net.dempsy.router.RoutingStrategy) NodeAddress(net.dempsy.transport.NodeAddress) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

KeyedMessageWithType (net.dempsy.messages.KeyedMessageWithType)26 Test (org.junit.Test)21 InstanceWrapper (net.dempsy.container.locking.LockingContainer.InstanceWrapper)7 NodeAddress (net.dempsy.transport.NodeAddress)5 DempsyException (net.dempsy.DempsyException)4 Container (net.dempsy.container.Container)4 RoutingStrategy (net.dempsy.router.RoutingStrategy)4 ContainerAddress (net.dempsy.router.RoutingStrategy.ContainerAddress)4 Assert.assertTrue (org.junit.Assert.assertTrue)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)3 Infrastructure (net.dempsy.Infrastructure)3 Manager (net.dempsy.Manager)3 ClusterInfoException (net.dempsy.cluster.ClusterInfoException)3 ClusterInfoSession (net.dempsy.cluster.ClusterInfoSession)3 ClusterId (net.dempsy.config.ClusterId)3 ContainerException (net.dempsy.container.ContainerException)3 KeyedMessage (net.dempsy.messages.KeyedMessage)3 RoutingStrategyManager (net.dempsy.router.RoutingStrategyManager)3