Exemplo n.º 1
0
 protected MsmqMessageProducerBase(string queueName, Func <MessageQueueTransactionType> transactionType)
 {
     _name            = queueName + "~producer";
     _queue           = MessageQueueFactory.GetOrCreateMessageQueue(queueName);
     _transactionType = transactionType;
 }
        private IEnumerable <IObservable <MessageEx> > GetMessageStream(string sourceName, bool isChild)
        {
            MessageQueue queue         = MessageQueueFactory.GetOrCreateMessageQueue(sourceName);
            var          messageOrigin = new MessageOrigin
            {
                Name = sourceName
            };

            Func <IObservable <Message> > recieveObservableFactory = Observable.FromAsyncPattern(
                (callback, obj) =>
            {
                //Wait infinite time here. Otherwise memory leak occurs.
                return(queue.BeginPeek(TimeSpan.FromMilliseconds(UInt32.MaxValue), obj, callback));
            },
                asyncResult => EndPeekAndReceive(queue, asyncResult));

            while (true)
            {
                var messagesStream = recieveObservableFactory().Select(m => new MessageEx {
                    Message       = m,
                    MessageOrigin = messageOrigin,
                    DoReceive     = () => queue.Receive(TimeSpan.FromSeconds(0), _receiveTransactionType)
                })
                                     .Catch((MessageQueueException e) =>
                {
                    if (e.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
                    {
                        _log.Info(LoggerContext.New(sourceName), "Msmq peek timeout occurs");
                        return(Observable.Return <MessageEx>(null));
                    }
                    if (e.MessageQueueErrorCode == MessageQueueErrorCode.AccessDenied)
                    {
                        WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();

                        string accessDeniedMessage = string.Format("Do not have permission to access queue [{0}]. Make sure that the current user [{1}] has permission to Send, Receive, and Peek  from this queue.", queue.QueueName, windowsIdentity != null ? windowsIdentity.Name : "no windows identity");
                        _log.Fatal(LoggerContext.New(sourceName), accessDeniedMessage, e);
                        try
                        {
                            EventLog.WriteEntry("TargetProcess Plugin", accessDeniedMessage, EventLogEntryType.Error);
                        }
                        catch (Exception)
                        {
                            //skip exception
                        }

                        //kill the process only if we cannot access main queue (in case of OnDemand it is router queue, in case of OnSite it is main queue)
                        if (!isChild)
                        {
                            _log.Fatal(LoggerContext.New(sourceName), "NServiceBus will now exit.", e);
                            Thread.Sleep(10000);                                                                                                                     //long enough for someone to notice
                            Process.GetCurrentProcess().Kill();
                        }
                    }
                    var message = string.Format("Problem in peeking/receiving a message from queue: {0}", Enum.GetName(typeof(MessageQueueErrorCode), e.MessageQueueErrorCode));
                    if (e.MessageQueueErrorCode == MessageQueueErrorCode.ServiceNotAvailable || e.MessageQueueErrorCode == MessageQueueErrorCode.OperationCanceled)
                    {
                        //this exceptions occur after windows restart. This is normal situation.
                        _log.Fatal(LoggerContext.New(sourceName), message, e);
                    }
                    else
                    {
                        _log.Error(LoggerContext.New(sourceName), message, e);
                    }
                    Thread.Sleep(_waitMessageTimeout);
                    return(Observable.Return <MessageEx>(null));
                })
                                     .Catch((ObjectDisposedException e) =>
                {
                    _log.Fatal(LoggerContext.New(sourceName), "Queue has been disposed. Cannot continue operation. Please restart this process.", e);
                    Thread.Sleep(_waitMessageTimeout);
                    return(Observable.Return <MessageEx>(null));
                })
                                     .Catch((Exception e) =>
                {
                    _log.Error(LoggerContext.New(sourceName), "Error in peeking/receiving a message from queue.", e);
                    Thread.Sleep(_waitMessageTimeout);
                    return(Observable.Return <MessageEx>(null));
                });
                yield return(messagesStream);
            }
        }