/// <summary>
        /// Handles a ScheduleMe that has expired from the Pending queue. If it is time to send the message, the message is published to the destination queue.
        /// If the time has not yet come, put the message back into the Pending queue with a new expiry time.
        /// </summary>
        /// <param name="message"></param>
        private void Evaluate(ScheduleMe message)
        {
            log.DebugWrite("Received message for publish at {0}", message.WakeTime);

            if (!bus.IsConnected)
            {
                return;
            }

            try
            {
                // If wake time is past, publish the message
                var timeToPublish = TimeToPublish(message);
                if (timeToPublish < 5000)
                {
                    Publish(message);
                }
                else
                {
                    // otherwise put it back on the pending queue
                    ReQueue(message, timeToPublish);
                }
            }
            catch (Exception ex)
            {
                log.ErrorWrite(ex);
            }
        }
Beispiel #2
0
        public void CheckMessageType <TMessage>(
            Byte[] body,
            MessageProperties properties,
            MessageReceivedInfo messageReceivedInfo)
        {
            Preconditions.CheckNotNull(body, "body");
            Preconditions.CheckNotNull(properties, "properties");
            Preconditions.CheckNotNull(messageReceivedInfo, "messageReceivedInfo");

            Type messageType = null;
            var  typeName    = typeNameSerializer.Serialize(typeof(TMessage));

            try
            {
                messageType = typeNameSerializer.DeSerialize(properties.Type);
            }
            catch (EasyNetQException easyNetQException)
            {
                logger.ErrorWrite(easyNetQException.Message);

                throw new EasyNetQInvalidMessageTypeException(easyNetQException.Message);
            }

            var consumeType = typeof(TMessage);

            if (!consumeType.IsAssignableFrom(messageType))
            {
                logger.ErrorWrite("Message type is incorrect. Expected '{0}', but was '{1}'",
                                  typeName, properties.Type);

                throw new EasyNetQInvalidMessageTypeException("Message type is incorrect. Expected '{0}', but was '{1}'",
                                                              typeName, properties.Type);
            }
        }
        public void InvokeUserMessageHandler(ConsumerExecutionContext context)
        {
            Preconditions.CheckNotNull(context, "context");

            logger.DebugWrite("Received \n\tRoutingKey: '{0}'\n\tCorrelationId: '{1}'\n\tConsumerTag: '{2}'" +
                              "\n\tDeliveryTag: {3}\n\tRedelivered: {4}",
                              context.Info.RoutingKey,
                              context.Properties.CorrelationId,
                              context.Info.ConsumerTag,
                              context.Info.DeliverTag,
                              context.Info.Redelivered);

            Task completionTask;

            try
            {
                completionTask = context.UserHandler(context.Body, context.Properties, context.Info);
            }
            catch (Exception exception)
            {
                completionTask = TaskHelpers.FromException(exception);
            }

            if (completionTask.Status == TaskStatus.Created)
            {
                logger.ErrorWrite("Task returned from consumer callback is not started. ConsumerTag: '{0}'",
                                  context.Info.ConsumerTag);
                return;
            }

            completionTask.ContinueWith(task => DoAck(context, GetAckStrategy(context, task)));
        }
Beispiel #4
0
        public void OnPublishTimerTick(object state)
        {
            try
            {
                if (!bus.IsConnected)
                {
                    log.InfoWrite("Not connected");
                    return;
                }

                // Keep track of exchanges that have already been declared this tick
                var declaredExchanges = new ConcurrentDictionary <Tuple <string, string>, IExchange>();
                Func <Tuple <string, string>, IExchange> declareExchange = exchangeNameType =>
                {
                    log.DebugWrite("Declaring exchange {0}, {1}", exchangeNameType.Item1, exchangeNameType.Item2);
                    return(bus.Advanced.ExchangeDeclare(exchangeNameType.Item1, exchangeNameType.Item2));
                };

                using (var scope = new TransactionScope())
                {
                    var scheduledMessages = scheduleRepository.GetPending();

                    foreach (var scheduledMessage in scheduledMessages)
                    {
                        // Binding key fallback is only provided here for backwards compatibility, will be removed in the future
                        log.DebugWrite("Publishing Scheduled Message with Routing Key: '{0}'", scheduledMessage.BindingKey);

                        var exchangeName = scheduledMessage.Exchange ?? scheduledMessage.BindingKey;
                        var exchangeType = scheduledMessage.ExchangeType ?? ExchangeType.Topic;

                        var exchange = declaredExchanges.GetOrAdd(new Tuple <string, string>(exchangeName, exchangeType), declareExchange);

                        var messageProperties = scheduledMessage.MessageProperties;

                        if (scheduledMessage.MessageProperties == null)
                        {
                            messageProperties = new MessageProperties {
                                Type = scheduledMessage.BindingKey
                            }
                        }
                        ;

                        var routingKey = scheduledMessage.RoutingKey ?? scheduledMessage.BindingKey;

                        bus.Advanced.Publish(
                            exchange,
                            routingKey,
                            false,
                            messageProperties,
                            scheduledMessage.InnerMessage);
                    }

                    scope.Complete();
                }
            }
            catch (Exception exception)
            {
                log.ErrorWrite("Error in schedule poll\r\n{0}", exception);
            }
        }
Beispiel #5
0
        public StartConsumingStatus StartConsuming(IPersistentConnection connection, ICollection <Tuple <IQueue, Func <byte[], MessageProperties, MessageReceivedInfo, Task> > > queueConsumerPairs, IConsumerConfiguration configuration)
        {
            Preconditions.CheckNotNull(connection, nameof(connection));
            Preconditions.CheckNotNull(queueConsumerPairs, nameof(queueConsumerPairs));
            Preconditions.CheckNotNull(configuration, nameof(configuration));


            IDictionary <string, object> arguments = new Dictionary <string, object>
            {
                { "x-priority", configuration.Priority },
                { "x-cancel-on-ha-failover", configuration.CancelOnHaFailover || connectionConfiguration.CancelOnHaFailover }
            };

            try
            {
                Model = connection.CreateModel();

                Model.BasicQos(0, configuration.PrefetchCount, true);


                _basicConsumers = new List <BasicConsumer>();

                foreach (var p in queueConsumerPairs)
                {
                    var queue       = p.Item1;
                    var onMessage   = p.Item2;
                    var consumerTag = conventions.ConsumerTagConvention();
                    try
                    {
                        var basicConsumers = new BasicConsumer(SingleBasicConsumerCancelled, consumerDispatcher, queue, eventBus, handlerRunner, onMessage, logger, Model);

                        Model.BasicConsume(
                            queue.Name,  // queue
                            false,       // noAck
                            consumerTag, // consumerTag
                            true,
                            configuration.IsExclusive,
                            arguments,       // arguments
                            basicConsumers); // consumer
                        _basicConsumers.Add(basicConsumers);

                        logger.InfoWrite("Declared Consumer. queue='{0}', consumer tag='{1}' prefetchcount={2} priority={3} x-cancel-on-ha-failover={4}",
                                         queue.Name, consumerTag, configuration.PrefetchCount, configuration.Priority, configuration.CancelOnHaFailover);
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorWrite("Consume failed. queue='{0}', consumer tag='{1}', message='{2}'",
                                          queue.Name, consumerTag, ex.Message);
                        return(StartConsumingStatus.Failed);
                    }
                }
            }
            catch (Exception exception)
            {
                logger.ErrorWrite("Consume failed. queue='{0}', message='{1}'",
                                  string.Join(";", queueConsumerPairs.Select(x => x.Item1.Name)), exception.Message);
                return(StartConsumingStatus.Failed);
            }
            return(StartConsumingStatus.Succeed);
        }
Beispiel #6
0
        void TryToConnect(object timer)
        {
            if (timer != null)
            {
                ((Timer)timer).Dispose();
            }

            logger.DebugWrite("Trying to connect");
            if (disposed)
            {
                return;
            }

            connectionFactory.Reset();
            do
            {
                try
                {
                    connection = connectionFactory.CreateConnection(); // A possible dispose race condition exists, whereby the Dispose() method may run while this loop is waiting on connectionFactory.CreateConnection() returning a connection.  In that case, a connection could be created and assigned to the connection variable, without it ever being later disposed, leading to app hang on shutdown.  The following if clause guards against this condition and ensures such connections are always disposed.
                    if (disposed)
                    {
                        connection.Dispose();
                        break;
                    }

                    connectionFactory.Success();
                }
                catch (SocketException socketException)
                {
                    LogException(socketException);
                }
                catch (BrokerUnreachableException brokerUnreachableException)
                {
                    LogException(brokerUnreachableException);
                }
            } while (!disposed && connectionFactory.Next());

            if (connectionFactory.Succeeded)
            {
                connection.ConnectionShutdown  += OnConnectionShutdown;
                connection.ConnectionBlocked   += OnConnectionBlocked;
                connection.ConnectionUnblocked += OnConnectionUnblocked;

                OnConnected();
                logger.InfoWrite("Connected to RabbitMQ. Broker: '{0}', Port: {1}, VHost: '{2}'",
                                 connectionFactory.CurrentHost.Host,
                                 connectionFactory.CurrentHost.Port,
                                 connectionFactory.Configuration.VirtualHost);
            }
            else
            {
                if (!disposed)
                {
                    logger.ErrorWrite("Failed to connect to any Broker. Retrying in {0}",
                                      connectionFactory.Configuration.ConnectIntervalAttempt);
                    StartTryToConnect();
                }
            }
        }
        public virtual AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            Preconditions.CheckNotNull(context, "context");
            Preconditions.CheckNotNull(exception, "exception");

            if (disposed || disposing)
            {
                logger.ErrorWrite(
                    "EasyNetQ Consumer Error Handler: DefaultConsumerErrorStrategy was already disposed, when attempting to handle consumer error.  This can occur when messaging is being shut down through disposal of the IBus.  Message will not be ackd to RabbitMQ server and will remain on the RabbitMQ queue.  Error message will not be published to error queue.\n" +
                    "ConsumerTag: {0}, DeliveryTag: {1}\n",
                    context.Info.ConsumerTag,
                    context.Info.DeliverTag);
                return(AckStrategies.NackWithRequeue);
            }

            try
            {
                Connect();

                using (var model = connection.CreateModel())
                {
                    var errorExchange = DeclareErrorExchangeQueueStructure(model, context);

                    var messageBody = CreateErrorMessage(context, exception);
                    var properties  = model.CreateBasicProperties();
                    properties.Persistent = true;
                    properties.Type       = typeNameSerializer.Serialize(typeof(Error));

                    model.BasicPublish(errorExchange, context.Info.RoutingKey, properties, messageBody);
                }
            }
            catch (BrokerUnreachableException)
            {
                // thrown if the broker is unreachable during initial creation.
                logger.ErrorWrite("EasyNetQ Consumer Error Handler cannot connect to Broker\n" +
                                  CreateConnectionCheckMessage());
            }
            catch (OperationInterruptedException interruptedException)
            {
                // thrown if the broker connection is broken during declare or publish.
                logger.ErrorWrite("EasyNetQ Consumer Error Handler: Broker connection was closed while attempting to publish Error message.\n" +
                                  string.Format("Exception was: '{0}'\n", interruptedException.Message) +
                                  CreateConnectionCheckMessage());
            }
            catch (Exception unexpectedException)
            {
                // Something else unexpected has gone wrong :(
                logger.ErrorWrite("EasyNetQ Consumer Error Handler: Failed to publish error message\nException is:\n"
                                  + unexpectedException);
            }
            return(AckStrategies.Ack);
        }
Beispiel #8
0
        private void CheckMessageType <TMessage>(MessageProperties properties)
        {
            var typeName = serializeType(typeof(TMessage));

            if (properties.Type != typeName)
            {
                logger.ErrorWrite("Message type is incorrect. Expected '{0}', but was '{1}'",
                                  typeName, properties.Type);

                throw new EasyNetQInvalidMessageTypeException("Message type is incorrect. Expected '{0}', but was '{1}'",
                                                              typeName, properties.Type);
            }
        }
        public void OnPublishTimerTick(object state)
        {
            if (!bus.IsConnected)
            {
                return;
            }
            try
            {
                using (var scope = new TransactionScope())
                {
                    var scheduledMessages = scheduleRepository.GetPending();

                    foreach (var scheduledMessage in scheduledMessages)
                    {
                        // Binding key fallback is only provided here for backwards compatibility, will be removed in the future
                        log.DebugWrite(string.Format(
                                           "Publishing Scheduled Message with Routing Key: '{0}'", scheduledMessage.BindingKey));

                        var exchangeName = scheduledMessage.Exchange ?? scheduledMessage.BindingKey;
                        var exchangeType = scheduledMessage.ExchangeType ?? ExchangeType.Topic;

                        var exchange          = bus.Advanced.ExchangeDeclare(exchangeName, exchangeType);
                        var messageProperties = scheduledMessage.MessageProperties;

                        if (scheduledMessage.MessageProperties == null)
                        {
                            messageProperties = new MessageProperties {
                                Type = scheduledMessage.BindingKey
                            }
                        }
                        ;

                        var routingKey = scheduledMessage.RoutingKey ?? scheduledMessage.BindingKey;

                        bus.Advanced.Publish(
                            exchange,
                            routingKey,
                            false,
                            false,
                            messageProperties,
                            scheduledMessage.InnerMessage);
                    }

                    scope.Complete();
                }
            }
            catch (Exception exception)
            {
                log.ErrorWrite("Error in schedule pol\r\n{0}", exception);
            }
        }
        void TryToConnect(object timer)
        {
            if (timer != null)
            {
                ((Timer)timer).Dispose();
            }

            logger.DebugWrite("Trying to connect");
            if (disposed)
            {
                return;
            }

            connectionFactory.Reset();
            do
            {
                try
                {
                    connection = connectionFactory.CreateConnection();
                    connectionFactory.Success();
                }
                catch (SocketException socketException)
                {
                    LogException(socketException);
                }
                catch (BrokerUnreachableException brokerUnreachableException)
                {
                    LogException(brokerUnreachableException);
                }
            } while (connectionFactory.Next());

            if (connectionFactory.Succeeded)
            {
                connection.ConnectionShutdown  += OnConnectionShutdown;
                connection.ConnectionBlocked   += OnConnectionBlocked;
                connection.ConnectionUnblocked += OnConnectionUnblocked;

                OnConnected();
                logger.InfoWrite("Connected to RabbitMQ. Broker: '{0}', Port: {1}, VHost: '{2}'",
                                 connectionFactory.CurrentHost.Host,
                                 connectionFactory.CurrentHost.Port,
                                 connectionFactory.Configuration.VirtualHost);
            }
            else
            {
                logger.ErrorWrite("Failed to connect to any Broker. Retrying in {0} ms\n",
                                  connectAttemptIntervalMilliseconds);
                StartTryToConnect();
            }
        }
Beispiel #11
0
        public StartConsumingStatus StartConsuming(
            IPersistentConnection connection,
            IQueue queue,
            Func <byte[], MessageProperties, MessageReceivedInfo, Task> onMessage,
            IConsumerConfiguration configuration
            )
        {
            Preconditions.CheckNotNull(connection, "connection");
            Preconditions.CheckNotNull(queue, "queue");
            Preconditions.CheckNotNull(onMessage, "onMessage");
            Preconditions.CheckNotNull(configuration, "configuration");

            this.queue         = queue;
            this.onMessage     = onMessage;
            this.configuration = configuration;

            var consumerTag = conventions.ConsumerTagConvention();
            IDictionary <string, object> arguments = new Dictionary <string, object>
            {
                { "x-priority", configuration.Priority },
                { "x-cancel-on-ha-failover", configuration.CancelOnHaFailover || connectionConfiguration.CancelOnHaFailover }
            };

            try
            {
                Model = connection.CreateModel();

                Model.BasicQos(0, configuration.PrefetchCount, false);

                Model.BasicConsume(
                    queue.Name,         // queue
                    false,              // noAck
                    consumerTag,        // consumerTag
                    true,
                    configuration.IsExclusive,
                    arguments,          // arguments
                    this);              // consumer

                logger.InfoWrite("Declared Consumer. queue='{0}', consumer tag='{1}' prefetchcount={2} priority={3} x-cancel-on-ha-failover={4}",
                                 queue.Name, consumerTag, configuration.PrefetchCount, configuration.Priority, configuration.CancelOnHaFailover);
            }
            catch (Exception exception)
            {
                logger.ErrorWrite("Consume failed. queue='{0}', consumer tag='{1}', message='{2}'",
                                  queue.Name, consumerTag, exception.Message);
                return(StartConsumingStatus.Failed);
            }
            return(StartConsumingStatus.Succeed);
        }
Beispiel #12
0
        public void OnPublishTimerTick(object state)
        {
            if (!bus.IsConnected)
            {
                return;
            }
            try
            {
                using (var scope = new TransactionScope())
                {
                    var scheduledMessages = scheduleRepository.GetPending();
                    foreach (var scheduledMessage in scheduledMessages)
                    {
                        log.DebugWrite(string.Format(
                                           "Publishing Scheduled Message with Routing Key: '{0}'", scheduledMessage.BindingKey));
                        rawByteBus.RawPublish(scheduledMessage.BindingKey, scheduledMessage.InnerMessage);
                    }

                    scope.Complete();
                }
            }
            catch (Exception exception)
            {
                log.ErrorWrite("Error in schedule pol\r\n{0}", exception);
            }
        }
Beispiel #13
0
        // NOTE: refactoring tools might suggest this method is never invoked. Ignore them it
        // _is_ invoked by the GetHandler(Type messsageType) method below by reflection.
        public Func <IMessage <T>, MessageReceivedInfo, Task> GetHandler <T>() where T : class
        {
            // return (Func<IMessage<T>, MessageReceivedInfo, Task>)GetHandler(typeof(T));
            var messageType = typeof(T);

            if (handlers.ContainsKey(messageType))
            {
                return((Func <IMessage <T>, MessageReceivedInfo, Task>)handlers[messageType]);
            }

            // no exact handler match found, so let's see if we can find a handler that
            // handles a supertype of the consumed message.
            foreach (var handlerType in handlers.Keys.Where(type => type.IsAssignableFrom(messageType)))
            {
                return((Func <IMessage <T>, MessageReceivedInfo, Task>)handlers[handlerType]);
            }

            if (ThrowOnNoMatchingHandler)
            {
                logger.ErrorWrite("No handler found for message type {0}", messageType.Name);
                throw new EasyNetQException("No handler found for message type {0}", messageType.Name);
            }

            return((message, info) => Task.Factory.StartNew(() => { }));
        }
Beispiel #14
0
        public void InvokeChannelAction(Action <IModel> channelAction, DateTime startTime)
        {
            Preconditions.CheckNotNull(channelAction, "channelAction");
            //    var startTime = DateTime.UtcNow;
            var retryTimeout = TimeSpan.FromMilliseconds(50);

            while (!IsTimedOut(startTime))
            {
                try
                {
                    var channel = OpenChannel();
                    channelAction(channel);
                    return;
                }
                catch (OperationInterruptedException exception)
                {
                    CloseChannel();
                    if (NeedRethrow(exception))
                    {
                        throw;
                    }
                }
                catch (EasyNetQException)
                {
                    CloseChannel();
                }

                Thread.Sleep(retryTimeout);

                retryTimeout = retryTimeout.Double();
            }
            logger.ErrorWrite("Channel action timed out. Throwing exception to client. Start Time = {0}", startTime);
            throw new TimeoutException("The operation requested on PersistentChannel timed out.");
        }
        public ConsumerDispatcher(ConnectionConfiguration configuration, IEasyNetQLogger logger)
        {
            Preconditions.CheckNotNull(configuration, "configuration");
            Preconditions.CheckNotNull(logger, "logger");

            queue = new BlockingCollection <Action>();

            var thread = new Thread(_ =>
            {
                Action action;
                while (!disposed && queue.TryTake(out action, -1))
                {
                    try
                    {
                        action();
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorWrite(exception);
                    }
                }
            })
            {
                Name = "EasyNetQ consumer dispatch thread", IsBackground = configuration.UseBackgroundThreads
            };

            thread.Start();
        }
Beispiel #16
0
        /// <inheritdoc />
        public override void InvokeUserMessageHandler(ConsumerExecutionContext context)
        {
            _logger.DebugWrite("Received \n\tRoutingKey: '{0}'\n\tCorrelationId: '{1}'\n\tConsumerTag: '{2}'\n\tDeliveryTag: {3}\n\tRedelivered: {4}",
                               context.Info.RoutingKey,
                               context.Properties.CorrelationId,
                               context.Info.ConsumerTag,
                               context.Info.DeliverTag,
                               context.Info.Redelivered);

            Task completionTask;

            try {
                completionTask = _policy.Execute(() => {
                    var task = context.UserHandler(context.Body, context.Properties, context.Info);

                    if (task.IsFaulted)
                    {
                        throw task.Exception.GetBaseException();
                    }

                    return(task);
                });
            }
            catch (Exception exception) {
                completionTask = TaskHelpers.FromException(exception);
            }

            if (completionTask.Status == TaskStatus.Created)
            {
                _logger.ErrorWrite("Task returned from consumer callback is not started. ConsumerTag: '{0}'", context.Info.ConsumerTag);
                return;
            }

            completionTask.ContinueWith(task => base.DoAck(context, base.GetAckStrategy(context, task)));
        }
Beispiel #17
0
        public ConsumerDispatcher(IEasyNetQLogger logger)
        {
            Preconditions.CheckNotNull(logger, "logger");

            queue = new BlockingCollection <Action>();

            dispatchThread = new Thread(_ =>
            {
                Action action;
                while (!disposed && queue.TryTake(out action, -1))
                {
                    try
                    {
                        action();
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorWrite(exception);
                    }
                }
            })
            {
                Name = "EasyNetQ consumer dispatch thread"
            };
            dispatchThread.Start();
        }
Beispiel #18
0
        void TryToConnect(object timer)
        {
            if (timer != null)
            {
                ((Timer)timer).Dispose();
            }

            logger.DebugWrite("Trying to connect");
            if (disposed)
            {
                return;
            }
            try
            {
                connection = connectionFactory.CreateConnection();
                connection.ConnectionShutdown += OnConnectionShutdown;

                if (Connected != null)
                {
                    Connected();
                }
                logger.InfoWrite("Connected to RabbitMQ. Broker: '{0}', VHost: '{1}'", connectionFactory.HostName, connectionFactory.VirtualHost);
            }
            catch (BrokerUnreachableException brokerUnreachableException)
            {
                logger.ErrorWrite("Failed to connect to Broker: '{0}', VHost: '{1}'. Retrying in {2} ms\n" +
                                  "Check HostName, VirtualHost, Username and Password.\n" +
                                  "ExceptionMessage: {3}",
                                  connectionFactory.HostName,
                                  connectionFactory.VirtualHost,
                                  connectAttemptIntervalMilliseconds,
                                  brokerUnreachableException.Message);
                StartTryToConnect();
            }
        }
Beispiel #19
0
        public ConsumerDispatcher(IEasyNetQLogger logger)
        {
            Preconditions.CheckNotNull(logger, "logger");

            internalQueue = new ConcurrentQueue<Action>();
            queue = new BlockingCollection<Action>(internalQueue);

            dispatchThread = new Thread(_ =>
                {
                    try
                    {
                        while (true)
                        {
                            if (disposed) break;

                            queue.Take()();
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        // InvalidOperationException is thrown when Take is called after
                        // queue.CompleteAdding(), this is signals that this class is being
                        // disposed, so we allow the thread to complete.
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorWrite(exception);
                    }
                }) { Name = "EasyNetQ consumer dispatch thread" };
            dispatchThread.Start();
        }
Beispiel #20
0
        public void HandleBasicDeliver(
            string consumerTag,
            ulong deliveryTag,
            bool redelivered,
            string exchange,
            string routingKey,
            IBasicProperties properties,
            byte[] body)
        {
            logger.DebugWrite("HandleBasicDeliver on consumer: {0}, deliveryTag: {1}", consumerTag, deliveryTag);

            if (disposed)
            {
                // this message's consumer has stopped, so just return
                logger.InfoWrite("Consumer has stopped running. Consumer '{0}' on queue '{1}'. Ignoring message",
                                 ConsumerTag, queue.Name);
                return;
            }

            if (onMessage == null)
            {
                logger.ErrorWrite("User consumer callback, 'onMessage' has not been set for consumer '{0}'." +
                                  "Please call InternalConsumer.StartConsuming before passing the consumer to basic.consume",
                                  ConsumerTag);
                return;
            }

            var messageReceivedInfo = new MessageReceivedInfo(consumerTag, deliveryTag, redelivered, exchange, routingKey, queue.Name);
            var messsageProperties  = new MessageProperties(properties);
            var context             = new ConsumerExecutionContext(onMessage, messageReceivedInfo, messsageProperties, body, this);

            consumerDispatcher.QueueAction(() => handlerRunner.InvokeUserMessageHandler(context));
        }
        public Func <IMessage, MessageReceivedInfo, Task> GetHandler(Type messageType)
        {
            Func <IMessage, MessageReceivedInfo, Task> func;

            if (handlers.TryGetValue(messageType, out func))
            {
                return(func);
            }

            // no exact handler match found, so let's see if we can find a handler that
            // handles a supertype of the consumed message.
            var handlerType = handlers.Keys.FirstOrDefault(type => type.IsAssignableFrom(messageType));

            if (handlerType != null)
            {
                return(handlers[handlerType]);
            }

            if (ThrowOnNoMatchingHandler)
            {
                logger.ErrorWrite("No handler found for message type {0}", messageType.Name);
                throw new EasyNetQException("No handler found for message type {0}", messageType.Name);
            }

            return((message, info) => Task.Factory.StartNew(() => { }));
        }
Beispiel #22
0
        public void OnPublishTimerTick(object state)
        {
            if (!bus.IsConnected)
            {
                return;
            }
            try
            {
                using (var scope = new TransactionScope())
                    using (var channel = bus.Advanced.OpenPublishChannel())
                    {
                        var scheduledMessages = scheduleRepository.GetPending();
                        foreach (var scheduledMessage in scheduledMessages)
                        {
                            log.DebugWrite(string.Format(
                                               "Publishing Scheduled Message with Routing Key: '{0}'", scheduledMessage.BindingKey));

                            var exchange = Exchange.DeclareTopic(scheduledMessage.BindingKey);
                            channel.Publish(
                                exchange,
                                scheduledMessage.BindingKey,
                                new MessageProperties {
                                Type = scheduledMessage.BindingKey
                            },
                                scheduledMessage.InnerMessage);
                        }

                        scope.Complete();
                    }
            }
            catch (Exception exception)
            {
                log.ErrorWrite("Error in schedule pol\r\n{0}", exception);
            }
        }
        public IBasicGetResult <T> Get <T>(IQueue queue) where T : class
        {
            Preconditions.CheckNotNull(queue, "queue");
            var result = Get(queue);

            if (result.Body == null)
            {
                logger.DebugWrite("... but no message was available on queue '{0}'", queue.Name);
                return(new BasicGetResult <T>());
            }
            else
            {
                var message = messageSerializationStrategy.DeserializeMessage(result.Properties, result.Body);
                if (message.MessageType == typeof(T))
                {
                    return(new BasicGetResult <T>(message.Message));
                }
                else
                {
                    logger.ErrorWrite("Incorrect message type returned from Get." +
                                      "Expected {0}, but was {1}", typeof(T).Name, message.MessageType.Name);
                    throw new EasyNetQException("Incorrect message type returned from Get." +
                                                "Expected {0}, but was {1}", typeof(T).Name, message.MessageType.Name);
                }
            }
        }
Beispiel #24
0
        public ConsumerDispatcher(IEasyNetQLogger logger)
        {
            Preconditions.CheckNotNull(logger, "logger");

            dispatchThread = new Thread(_ =>
            {
                try
                {
                    while (true)
                    {
                        if (disposed)
                        {
                            break;
                        }

                        queue.Take()();
                    }
                }
                catch (InvalidOperationException)
                {
                    // InvalidOperationException is thrown when Take is called after
                    // queue.CompleteAdding(), this is signals that this class is being
                    // disposed, so we allow the thread to complete.
                }
                catch (Exception exception)
                {
                    logger.ErrorWrite(exception);
                }
            })
            {
                Name = "EasyNetQ consumer dispatch thread"
            };
            dispatchThread.Start();
        }
Beispiel #25
0
 private void InvokeChannelActionInternal(Action <IModel> channelAction, DateTime startTime)
 {
     if (IsTimedOut(startTime))
     {
         logger.ErrorWrite("Channel action timed out. Throwing exception to client.");
         throw new TimeoutException("The operation requested on PersistentChannel timed out.");
     }
     try
     {
         channelAction(Channel);
     }
     catch (OperationInterruptedException exception)
     {
         try
         {
             var amqpException = AmqpExceptionGrammar.ParseExceptionString(exception.Message);
             if (amqpException.Code == AmqpException.ConnectionClosed)
             {
                 OnConnectionDisconnected(null);
                 WaitForReconnectionOrTimeout(startTime);
                 InvokeChannelActionInternal(channelAction, startTime);
             }
             else
             {
                 throw;
             }
         }
         catch (Sprache.ParseException)
         {
             throw exception;
         }
     }
 }
Beispiel #26
0
 public void Cancel(UnscheduleMe unscheduleMe)
 {
     ThreadPool.QueueUserWorkItem(state =>
                                  WithStoredProcedureCommand(dialect.CancelProcedureName, command =>
     {
         try
         {
             AddParameter(command, dialect.CancellationKeyParameterName, unscheduleMe.CancellationKey, DbType.String);
             command.ExecuteNonQuery();
         }
         catch (Exception ex)
         {
             log.ErrorWrite("ScheduleRepository.Cancel threw an exception {0}", ex);
         }
     })
                                  );
 }
Beispiel #27
0
 private void HandleErrorInSubscriptionHandler(
     BasicDeliverEventArgs basicDeliverEventArgs,
     SubscriptionInfo subscriptionInfo,
     Exception exception)
 {
     logger.ErrorWrite(BuildErrorMessage(basicDeliverEventArgs, exception));
     consumerErrorStrategy.HandleConsumerError(basicDeliverEventArgs, exception);
     DoAck(basicDeliverEventArgs, subscriptionInfo);
 }
        private void HandleMessageDelivery(BasicDeliverEventArgs basicDeliverEventArgs)
        {
            var consumerTag = basicDeliverEventArgs.ConsumerTag;

            if (!subscriptions.ContainsKey(consumerTag))
            {
                throw new EasyNetQException("No callback found for ConsumerTag {0}", consumerTag);
            }

            logger.DebugWrite("Subscriber Recieved {0}, CorrelationId {1}",
                              basicDeliverEventArgs.RoutingKey, basicDeliverEventArgs.BasicProperties.CorrelationId);

            var subscriptionInfo = subscriptions[consumerTag];


            try
            {
                var completionTask = subscriptionInfo.Callback(
                    consumerTag,
                    basicDeliverEventArgs.DeliveryTag,
                    basicDeliverEventArgs.Redelivered,
                    basicDeliverEventArgs.Exchange,
                    basicDeliverEventArgs.RoutingKey,
                    basicDeliverEventArgs.BasicProperties,
                    basicDeliverEventArgs.Body);

                completionTask.ContinueWith(task =>
                {
                    if (task.IsFaulted)
                    {
                        var exception = task.Exception;
                        logger.ErrorWrite(BuildErrorMessage(basicDeliverEventArgs, exception));
                        consumerErrorStrategy.HandleConsumerError(basicDeliverEventArgs, exception);
                    }
                    DoAck(basicDeliverEventArgs, subscriptionInfo);
                });
            }
            catch (Exception exception)
            {
                logger.ErrorWrite(BuildErrorMessage(basicDeliverEventArgs, exception));
                consumerErrorStrategy.HandleConsumerError(basicDeliverEventArgs, exception);
                DoAck(basicDeliverEventArgs, subscriptionInfo);
            }
        }
        public virtual PostExceptionAckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
        {
            Preconditions.CheckNotNull(context, "context");
            Preconditions.CheckNotNull(exception, "exception");

            try
            {
                Connect();

                using (var model = connection.CreateModel())
                {
                    var errorExchange = DeclareErrorExchangeQueueStructure(model, context);

                    var messageBody = CreateErrorMessage(context, exception);
                    var properties  = model.CreateBasicProperties();
                    properties.SetPersistent(true);
                    properties.Type = typeNameSerializer.Serialize(typeof(Error));

                    model.BasicPublish(errorExchange, context.Info.RoutingKey, properties, messageBody);
                }
            }
            catch (BrokerUnreachableException)
            {
                // thrown if the broker is unreachable during initial creation.
                logger.ErrorWrite("EasyNetQ Consumer Error Handler cannot connect to Broker\n" +
                                  CreateConnectionCheckMessage());
            }
            catch (OperationInterruptedException interruptedException)
            {
                // thrown if the broker connection is broken during declare or publish.
                logger.ErrorWrite("EasyNetQ Consumer Error Handler: Broker connection was closed while attempting to publish Error message.\n" +
                                  string.Format("Message was: '{0}'\n", interruptedException.Message) +
                                  CreateConnectionCheckMessage());
            }
            catch (Exception unexpectedException)
            {
                // Something else unexpected has gone wrong :(
                logger.ErrorWrite("EasyNetQ Consumer Error Handler: Failed to publish error message\nException is:\n"
                                  + unexpectedException);
            }
            return(Consumer.PostExceptionAckStrategy.ShouldAck);
        }
Beispiel #30
0
        public void InvokeUserMessageHandler(ConsumerExecutionContext context)
        {
            Preconditions.CheckNotNull(context, "context");

            logger.DebugWrite("Recieved \n\tRoutingKey: '{0}'\n\tCorrelationId: '{1}'\n\tConsumerTag: '{2}'" +
                              "\n\tDeliveryTag: {3}\n\tRedelivered: {4}",
                              context.Info.RoutingKey,
                              context.Properties.CorrelationId,
                              context.Info.ConsumerTag,
                              context.Info.DeliverTag,
                              context.Info.Redelivered);

            try
            {
                var completionTask = context.UserHandler(context.Body, context.Properties, context.Info);

                if (completionTask.Status == TaskStatus.Created)
                {
                    logger.ErrorWrite("Task returned from consumer callback is not started. ConsumerTag: '{0}'",
                                      context.Info.ConsumerTag);
                }
                else
                {
                    completionTask.ContinueWith(task =>
                    {
                        if (task.IsFaulted)
                        {
                            var exception = task.Exception;
                            HandleErrorInSubscriptionHandler(context, exception);
                        }
                        else
                        {
                            DoAck(context, SuccessAckStrategy);
                        }
                    });
                }
            }
            catch (Exception exception)
            {
                HandleErrorInSubscriptionHandler(context, exception);
            }
        }
        public virtual void HandleConsumerError(BasicDeliverEventArgs deliverArgs, Exception exception)
        {
            try
            {
                Connect();

                using (var model = connection.CreateModel())
                {
                    var errorExchange = DeclareErrorExchangeQueueStructure(model, deliverArgs.RoutingKey);

                    var messageBody = CreateErrorMessage(deliverArgs, exception);
                    var properties  = model.CreateBasicProperties();
                    properties.SetPersistent(true);
                    properties.Type = TypeNameSerializer.Serialize(typeof(Error));

                    model.BasicPublish(errorExchange, deliverArgs.RoutingKey, properties, messageBody);
                }
            }
            catch (BrokerUnreachableException)
            {
                // thrown if the broker is unreachable during initial creation.
                logger.ErrorWrite("EasyNetQ Consumer Error Handler cannot connect to Broker\n" +
                                  CreateConnectionCheckMessage());
            }
            catch (OperationInterruptedException interruptedException)
            {
                // thrown if the broker connection is broken during declare or publish.
                logger.ErrorWrite("EasyNetQ Consumer Error Handler: Broker connection was closed while attempting to publish Error message.\n" +
                                  string.Format("Message was: '{0}'\n", interruptedException.Message) +
                                  CreateConnectionCheckMessage());
            }
            catch (Exception unexpecctedException)
            {
                // Something else unexpected has gone wrong :(
                logger.ErrorWrite("EasyNetQ Consumer Error Handler: Failed to publish error message\nException is:\n"
                                  + unexpecctedException);
            }
        }
        public ConsumerDispatcher(IEasyNetQLogger logger)
        {
            Preconditions.CheckNotNull(logger, "logger");

            queue = new BlockingCollection<Action>();

            dispatchThread = new Thread(_ =>
                {
                    Action action;
                    while(!disposed && queue.TryTake(out action, -1))
                    {
                        try
                        {
                            action();
                        }
                        catch (Exception exception)
                        {
                            logger.ErrorWrite(exception);
                        }
                    }
                }) { Name = "EasyNetQ consumer dispatch thread" };
            dispatchThread.Start();
        }
Beispiel #33
0
        public ConsumerDispatcher(ConnectionConfiguration configuration, IEasyNetQLogger logger)
        {
            Preconditions.CheckNotNull(configuration, "configuration");
            Preconditions.CheckNotNull(logger, "logger");

            queue = new BlockingCollection<Action>();

            var thread = new Thread(_ =>
            {
                Action action;
                while (!disposed && queue.TryTake(out action, -1))
                {
                    try
                    {
                        action();
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorWrite(exception);
                    }
                }
            }) {Name = "EasyNetQ consumer dispatch thread", IsBackground = configuration.UseBackgroundThreads};
            thread.Start();
        }