Example #1
0
        /// <summary>
        /// Takes a given type T and serializes it to json before
        /// wrapping it in an MSMQ message and placing it on a queue.
        /// For the lifetime of the bus, if muliple queues are defined then each time Send is invoked:
        /// a) if AutoDistributeOnSend is true then a message is placed on the next queue in the list in a round-robin fashion
        /// b) otherwise a message is placed on all queues
        /// </summary>
        public void Send <T>(T dto)
        {
            GuardAgainstInvalidWriteQueues();
            GuardAgainstInvalidErrorQueue();

            // configure the pipeline for sending a message
            var pipe = new PipeLine <MessageContext>();

            pipe.AddAspect(new TransactionAspect <MessageContext>());
            pipe.AddAspect(new LoggingAspect <MessageContext>());
            pipe.AddAspect(new MoveToErrorQueueAspect <MessageContext>());
            pipe.Register(new SendMessage());

            if (_config.AutoDistributeOnSend)
            {
                var message = CreateMsmqMessageFromDto(dto);
                var ctx     = new MessageContext {
                    Message = message, Config = _config, WriteQueue = _writeQueues.ElementAt(_nextQueue), ErrorQueue = _errorQueue, OpType = SendOperation, OnStep = LogMessage, OnComplete = SetNextQueueIndex
                };
                pipe.Invoke(ctx);
            }
            else
            {
                foreach (var writeQueue in _writeQueues)
                {
                    var message = CreateMsmqMessageFromDto(dto);
                    var ctx     = new MessageContext {
                        Message = message, Config = _config, WriteQueue = writeQueue, ErrorQueue = _errorQueue, OpType = SendOperation, OnStep = LogMessage
                    };
                    pipe.Invoke(ctx);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Takes a given type T and serializes it to json before wrapping it in an MSMQ message and placing it on a queue.
        /// For the lifetime of the bus, if muliple queues are defined then each time Send is invoked:
        /// a) if a destination has been passed in, send to that queue only
        /// b) or if AutoDistributeOnSend is true then a message is placed on the next queue in the list in a round-robin fashion
        /// c) otherwise a message is placed on all queues
        /// </summary>
        public void Send <T>(T dto, string destination = "")
        {
            GuardAgainstInvalidWriteQueues();
            GuardAgainstInvalidErrorQueue();

            destination = stripRemoteFrom(destination);

            // configure the pipeline for sending a message
            var pipe = new PipeLine <MessageContext>();

            pipe.AddAspect(new TransactionAspect <MessageContext>());
            pipe.AddAspect(new LoggingAspect <MessageContext>());
            pipe.AddAspect(new MoveToErrorQueueAspect <MessageContext>());
            pipe.Register(new SendMessage());

            // if destination passed in override the configured bus, assert that the destination is known and send to it
            if (!string.IsNullOrEmpty(destination) && !string.IsNullOrWhiteSpace(destination))
            {
                GuardAgainstUnknownQueue(destination);

                var queue   = _writeQueues.First(q => q.FormatName.EndsWith(destination));
                var message = CreateMsmqMessageFromDto(dto);
                var ctx     = new MessageContext {
                    Message = message, Config = _config, WriteQueue = queue, ErrorQueue = _errorQueue, OpType = SendOperation, OnStep = LogMessage, OnComplete = SetNextQueueIndex
                };
                pipe.Invoke(ctx);
                return;
            }

            // if applicable, send to the next queue as we carry out load balancing in a round robin fashion
            if (_config.AutoDistributeOnSend)
            {
                var message = CreateMsmqMessageFromDto(dto);
                var ctx     = new MessageContext {
                    Message = message, Config = _config, WriteQueue = _writeQueues.ElementAt(_nextQueue), ErrorQueue = _errorQueue, OpType = SendOperation, OnStep = LogMessage, OnComplete = SetNextQueueIndex
                };
                pipe.Invoke(ctx);
                return;
            }

            // otherwise send the same message to all defined write queues
            foreach (var writeQueue in _writeQueues)
            {
                var message = CreateMsmqMessageFromDto(dto);
                var ctx     = new MessageContext {
                    Message = message, Config = _config, WriteQueue = writeQueue, ErrorQueue = _errorQueue, OpType = SendOperation, OnStep = LogMessage
                };
                pipe.Invoke(ctx);
            }
        }
Example #3
0
        /// <summary>
        /// Reads messages off a queue, deserializes them into the
        /// specified type T and invokes registered handlers. Useful when
        /// you want to control when messages are processed i.e. at a set
        /// time every day, for example.
        /// </summary>
        public void Receive <T>()
        {
            GuardAgainstInvalidReadQueue();
            GuardAgainstInvalidErrorQueue();

            // configure the pipeline for receiving messages
            var pipe = new PipeLine <MessageContext>();

            pipe.AddAspect(new FailFastAspect <MessageContext>());
            pipe.AddAspect(new DiscardAspect <MessageContext>());
            pipe.AddAspect(new TransactionAspect <MessageContext>());
            pipe.AddAspect(new LoggingAspect <MessageContext>());
            pipe.AddAspect(new MoveToErrorQueueAspect <MessageContext>());
            pipe.AddAspect(new RemoveFromReadQueueAspect <MessageContext>());
            pipe.AddAspect(new RetryAspect <MessageContext>());
            pipe.Register(new InvokeUserHandlers <T>());

            foreach (Message message in _readQueue.PeekAllMessages())
            {
                var ctx = new MessageContext {
                    Message = message, Config = _config, ReadQueue = _readQueue, ErrorQueue = _errorQueue, Handlers = _handlers, OpType = ReceiveOperation, OnStep = LogMessage
                };
                pipe.Invoke(ctx);

                if (ctx.FailFast)
                {
                    break;
                }
            }
        }
Example #4
0
        /// <summary>
        /// Read messages containing the given type T off the defined
        /// error queue and moves them to the user defined read queue
        /// </summary>
        public void ReturnAllErrorMessages()
        {
            GuardAgainstInvalidReadQueue();
            GuardAgainstInvalidErrorQueue();

            try
            {
                // configure the pipeline for return all message to their original queue
                var pipe = new PipeLine <MessageContext>();
                pipe.AddAspect(new TransactionAspect <MessageContext>());
                pipe.AddAspect(new LoggingAspect <MessageContext>());
                pipe.Register(new ReturnToSource());

                foreach (Message message in _errorQueue.PeekAllMessages())
                {
                    var ctx = new MessageContext {
                        Message = message, Config = _config, ReadQueue = _readQueue, ErrorQueue = _errorQueue, OpType = ReturnOperation, OnStep = LogMessage
                    };
                    pipe.Invoke(ctx);
                }
            }
            catch (Exception ex)
            {
                throw new BusException($"A problem occurred retreiving messages from the error queue: {ex}");
            }
        }
Example #5
0
        /// <summary>
        /// Read specific message off the given read queue identified by the messageId parameter and copy it to one or more defined write queues
        /// </summary>
        /// <param name="messageId"></param>
        public void Copy(string messageId)
        {
            GuardAgainstInvalidReadQueue();
            GuardAgainstInvalidWriteQueues();

            try
            {
                // configure the pipeline for copying messages
                var pipe = new PipeLine <MessageContext>();
                pipe.AddAspect(new TransactionAspect <MessageContext>());
                pipe.AddAspect(new LoggingAspect <MessageContext>());
                pipe.Register(new CopyMessage());

                var message = _readQueue.PeekMessageBy(messageId);

                foreach (var queue in _writeQueues)
                {
                    var ctx = new MessageContext {
                        Message = message, Config = _config, ReadQueue = _readQueue, WriteQueue = queue, OpType = CopyOperation, OnStep = LogMessage
                    };
                    pipe.Invoke(ctx);
                }
            }
            catch (Exception ex)
            {
                throw new BusException($"A problem occurred copying message: {messageId} - error: {ex}");
            }
        }
Example #6
0
        /// <summary>
        /// Reads messages off a queue as they arrive, deserializes them into the
        /// specified type T and invokes registered handlers. This operation is
        /// asynchnronous meaning registered handlers will be invoked on the
        /// background thread.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void ReceiveAsync <T>()
        {
            GuardAgainstInvalidReadQueue();
            GuardAgainstInvalidErrorQueue();

            // configure the pipeline for receiving messages
            var pipe = new PipeLine <MessageContext>();

            pipe.AddAspect(new FailFastAspect <MessageContext>());
            pipe.AddAspect(new DiscardAspect <MessageContext>());
            pipe.AddAspect(new TransactionAspect <MessageContext>());
            pipe.AddAspect(new LoggingAspect <MessageContext>());
            pipe.AddAspect(new MoveToErrorQueueAspect <MessageContext>());
            pipe.AddAspect(new RemoveFromReadQueueAspect <MessageContext>());
            pipe.AddAspect(new RetryAspect <MessageContext>());
            pipe.Register(new InvokeUserHandlers <T>());

            _readQueue.ReceiveAsync(message => {
                var ctx = new MessageContext {
                    Message = message, Config = _config, ReadQueue = _readQueue, ErrorQueue = _errorQueue, Handlers = _handlers, OpType = ReceiveOperation, OnStep = LogMessage
                };
                pipe.Invoke(ctx);

                if (ctx.FailFast)
                {
                    LogMessage("Invoking StopReceiveAsync because FailFast equals true");
                    _readQueue.StopReceiveAsync();
                }
            });

            LogMessage("Receiving...");
        }
Example #7
0
        /// <summary>
        /// Peek specific message off the given read queue identified by the messageId parameter and return the body as a string
        /// </summary>
        public string ViewMessageBody(string messageId)
        {
            GuardAgainstInvalidReadQueue();

            try
            {
                string bodyAsString = string.Empty;
                var    pipe         = new PipeLine <MessageContext>();
                pipe.AddAspect(new TransactionAspect <MessageContext>());
                pipe.AddAspect(new LoggingAspect <MessageContext>());
                pipe.Register(new ViewMessage(s => bodyAsString = s));

                var message = _readQueue.PeekMessageBy(messageId);
                var ctx     = new MessageContext {
                    Message = message, Config = _config, ReadQueue = _readQueue, OpType = ViewOperation, OnStep = LogMessage
                };
                ctx.Message.Formatter = new BodyAsStringFormatter();
                pipe.Invoke(ctx);

                return(bodyAsString);
            }
            catch (Exception ex)
            {
                throw new BusException($"A problem occurred viewing message: {messageId} - error: {ex}");
            }
        }
Example #8
0
        public void InvokeTest()
        {
            var source = new[] { 1, 2, 3, 4, 5 };

            using (var p = new PipeLine(CancellationToken.None)) {
                var first  = p.Add(1, 10, source, i => i * 10);
                var second = p.AddSelectMany(1, 100, first.Results, i => Enumerable.Range(0, i));
                var list   = new List <int>();
                p.Invoke(() => { list.AddRange(second.Results.GetConsumingEnumerable()); });

                foreach (var x in list.OrderBy(x => x).Zip(source.Select(x => x * 10).SelectMany(x => Enumerable.Range(0, x)).OrderBy(x => x),
                                                           (s, t) => new { s, t }))
                {
                    Assert.Equal(x.s, x.t);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Read specific message off the defined error queue and move it to the user defined read queue
        /// </summary>
        public void ReturnErrorMessage(string id)
        {
            GuardAgainstInvalidReadQueue();
            GuardAgainstInvalidErrorQueue();

            try
            {
                // configure the pipeline for return a message to its original queue
                var pipe = new PipeLine <MessageContext>();
                pipe.AddAspect(new TransactionAspect <MessageContext>());
                pipe.AddAspect(new LoggingAspect <MessageContext>());
                pipe.Register(new ReturnToSource());

                Message message = _errorQueue.PeekMessageBy(id);
                var     ctx     = new MessageContext {
                    Message = message, Config = _config, ReadQueue = _readQueue, ErrorQueue = _errorQueue, OpType = ReturnOperation, OnStep = LogMessage
                };
                pipe.Invoke(ctx);
            }
            catch (Exception)
            {
                throw new BusException($"Message with id {id} was not found on the error queue");
            }
        }