Beispiel #1
0
        /// <summary>
        /// Handles the specified message.
        /// </summary>
        /// <param name="messageId">The message identifier.</param>
        /// <param name="timeOut">The time out.</param>
        /// <param name="queueWait">The queue wait.</param>
        /// <returns></returns>
        /// <exception cref="System.TimeoutException"></exception>
        public IReceivedMessage <TReceivedMessage> Handle(IMessageId messageId, TimeSpan timeOut, IQueueWait queueWait)
        {
            Guard.NotNull(() => messageId, messageId);
            Guard.NotNull(() => queueWait, queueWait);

            //use a message context, and talk to the transport directly
            //we are not going to use the consumer queue, because we are going to re-use the calling thread for all of the work below
            using (var context = _messageContextFactory.Create())
            {
                var recMessage = _receiveMessagesFactory.Create();

                //set message Id on the context, so that the transport knows we want a particular message
                context.Set(_configurationReceive.HeaderNames.StandardHeaders.RpcContext, _rpcContextFactory.Create(messageId, timeOut));

                //use a stop watch to determine when we have timed out
                var sw = new Stopwatch();
                sw.Start();
                while (true)
                {
                    var messageRec = recMessage.ReceiveMessage(context);
                    if (messageRec != null)
                    {
                        _commitMessage.Commit(context);
                        return((IReceivedMessage <TReceivedMessage>)_messageHandler.GenerateMessage(messageRec));
                    }
                    if (sw.ElapsedMilliseconds >= timeOut.TotalMilliseconds)
                    {
                        throw new TimeoutException();
                    }
                    queueWait.Wait();
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageProcessing"/> class.
        /// </summary>
        /// <param name="receiveMessages">The receive messages.</param>
        /// <param name="messageContextFactory">The message context factory.</param>
        /// <param name="queueWaitFactory">The queue wait factory.</param>
        /// <param name="log">The log.</param>
        /// <param name="processMessage">The process message.</param>
        /// <param name="receivePoisonMessage">The receive poison message.</param>
        /// <param name="rollbackMessage">rolls back a message when an exception occurs</param>
        public MessageProcessing(
            IReceiveMessagesFactory receiveMessages,
            IMessageContextFactory messageContextFactory,
            IQueueWaitFactory queueWaitFactory,
            ILogFactory log,
            ProcessMessage processMessage,
            IReceivePoisonMessage receivePoisonMessage,
            IRollbackMessage rollbackMessage)
        {
            Guard.NotNull(() => receiveMessages, receiveMessages);
            Guard.NotNull(() => messageContextFactory, messageContextFactory);
            Guard.NotNull(() => queueWaitFactory, queueWaitFactory);
            Guard.NotNull(() => log, log);
            Guard.NotNull(() => processMessage, processMessage);
            Guard.NotNull(() => receivePoisonMessage, receivePoisonMessage);
            Guard.NotNull(() => rollbackMessage, rollbackMessage);

            _receiveMessages       = receiveMessages.Create();
            _messageContextFactory = messageContextFactory;
            _log                  = log.Create();
            _processMessage       = processMessage;
            _receivePoisonMessage = receivePoisonMessage;
            _rollbackMessage      = rollbackMessage;

            _noMessageToProcessBackOffHelper      = new Lazy <IQueueWait>(queueWaitFactory.CreateQueueDelay);
            _seriousExceptionProcessBackOffHelper = new Lazy <IQueueWait>(queueWaitFactory.CreateFatalErrorDelay);
        }
        /// <summary>
        /// Tries the process a new incoming message.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        private async Task DoTryAsync(IMessageContext context)
        {
            var receiveMessage = _receiveMessages.Create();

            //this call must block; otherwise, the limitations enforced by the task scheduler will be ignored
            //calling the async method here may result in hundreds of de-queues at once, instead of the N set in the configuration
            var transportMessage = receiveMessage.ReceiveMessage(context);

            if (transportMessage == null)
            {
                //delay processing since we have no messages to process
                if (!_idle)
                {
                    Idle(this, EventArgs.Empty);
                    _idle = true;
                }
                _noMessageToProcessBackOffHelper.Value.Wait();
                return;
            }

            //reset the back off counter - we have a message to process, so the wait times are now reset
            _noMessageToProcessBackOffHelper.Value.Reset();
            //we are no longer idle
            if (_idle)
            {
                NotIdle(this, EventArgs.Empty);
                _idle = false;
            }

            //process the message
            await _processMessage.HandleAsync(context, transportMessage).ConfigureAwait(false);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageProcessing"/> class.
        /// </summary>
        /// <param name="receiveMessages">The receive messages.</param>
        /// <param name="messageContextFactory">The message context factory.</param>
        /// <param name="queueWaitFactory">The queue wait factory.</param>
        /// <param name="log">The log.</param>
        /// <param name="processMessage">The process message.</param>
        /// <param name="receivePoisonMessage">The receive poison message.</param>
        /// <param name="rollbackMessage">rolls back a message when an exception occurs</param>
        public MessageProcessing(
            IReceiveMessagesFactory receiveMessages,
            IMessageContextFactory messageContextFactory,
            IQueueWaitFactory queueWaitFactory,
            ILogFactory log,
            ProcessMessage processMessage,
            IReceivePoisonMessage receivePoisonMessage,
            IRollbackMessage rollbackMessage)
        {

            Guard.NotNull(() => receiveMessages, receiveMessages);
            Guard.NotNull(() => messageContextFactory, messageContextFactory);
            Guard.NotNull(() => queueWaitFactory, queueWaitFactory);
            Guard.NotNull(() => log, log);
            Guard.NotNull(() => processMessage, processMessage);
            Guard.NotNull(() => receivePoisonMessage, receivePoisonMessage);
            Guard.NotNull(() => rollbackMessage, rollbackMessage);

            _receiveMessages = receiveMessages.Create();
            _messageContextFactory = messageContextFactory;
            _log = log.Create();
            _processMessage = processMessage;
            _receivePoisonMessage = receivePoisonMessage;
            _rollbackMessage = rollbackMessage;

            _noMessageToProcessBackoffHelper = new Lazy<IQueueWait>(queueWaitFactory.CreateQueueDelay);
            _seriousExceptionProcessBackOffHelper = new Lazy<IQueueWait>(queueWaitFactory.CreateFatalErrorDelay);

        }