Пример #1
0
        /// <summary>
        /// Sends a message to the RabbitMQ broker.
        /// </summary>
        /// <remarks>
        /// If <see cref="RabbitPublisher.BasicProperties"/> is not set uses <see cref="BasicProperties"/> as default.
        /// </remarks>
        /// <param name="messageBody">The message to be sent.</param>
        /// <param name="publisher">Publisher information.</param>
        /// <param name="queue">Queue information.</param>
        /// <example>
        /// <code>
        /// ...
        /// var body = Encoding.UTF8.GetBytes(jsonItem);
        /// handler.SendMessage(body, publisher, queue);
        /// ...
        /// </code>
        /// </example>
        public void SendMessage(
            byte[] messageBody,
            RabbitPublisher publisher,
            RabbitQueue queue)
        {
            if (messageBody == default)
            {
                throw new ArgumentNullException(nameof(messageBody), "Message must not be null");
            }
            if (publisher == null)
            {
                throw new ArgumentNullException(nameof(publisher), "Publisher must not be null.");
            }
            if (queue == null)
            {
                throw new ArgumentNullException(nameof(queue), "Queue must not be null.");
            }

            using (var conn = ConnectionFactory.CreateConnection())
                using (var channel = conn.CreateModel())
                {
                    channel.QueueDeclare(queue: queue.Name,
                                         durable: queue.Durable,
                                         exclusive: queue.Exclusive,
                                         autoDelete: queue.AutoDelete);

                    channel.BasicPublish(exchange: publisher.Exchange,
                                         routingKey: publisher.RoutingKey,
                                         basicProperties: publisher.BasicProperties ?? this.BasicProperties,
                                         messageBody);
                }
        }
Пример #2
0
        /// <summary>
        /// Initiates a new thread for receiving messages.
        /// </summary>
        /// <remarks>
        /// <para>Automatically handles acknowledged and not acknowledged responses.</para>
        /// <para>Use <paramref name="messageReceived"/> to manipulate the message.</para>
        /// <para>Use <paramref name="exceptionReceived"/> to manipulate exceptions.</para>
        /// </remarks>
        /// <param name="queue">Queue information.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <param name="messageReceived">
        /// <para>Message received treatment.</para>
        /// <para>Usually message content is inside <see cref="BasicDeliverEventArgs.Body"/>.</para>
        /// </param>
        /// <param name="exceptionReceived">Exception treatment.</param>
        /// <param name="dieOnException">If an exception is thrown should the worker dies.</param>
        /// <example>
        /// <code>
        /// ...
        /// handler.ReceiveMessages(queue, cToken,
        ///     messageReceived: (model, ea) =>
        ///     {
        ///         var body = ea.Body.ToArray();
        ///         string jsonContent = Encoding.UTF8.GetString(body);
        ///         ...
        ///     },
        ///     exceptionReceived: (model, ea, exc) =>
        ///     {
        ///         logger.LogError("Something happened", exc);
        ///         ...
        ///     });
        /// ...
        /// </code>
        /// </example>
        public void ReceiveMessages(
            RabbitQueue queue,
            CancellationTokenSource cancellationToken,
            Action <object, BasicDeliverEventArgs> messageReceived,
            Action <object, BasicDeliverEventArgs, Exception> exceptionReceived = null,
            bool dieOnException = false)
        {
            if (queue == null)
            {
                throw new ArgumentNullException(paramName: nameof(queue), message: "Queue information must not be null.");
            }
            if (cancellationToken == default)
            {
                throw new ArgumentNullException(paramName: nameof(cancellationToken), message: "Cancellation token must not be null.");
            }
            if (messageReceived == null)
            {
                throw new ArgumentNullException(paramName: nameof(messageReceived), message: "Callback must not be null.");
            }

            Task.Factory.StartNew(() =>
            {
                using (var conn = ConnectionFactory.CreateConnection())
                    using (var channel = conn.CreateModel())
                    {
                        // maximum of 2 messages for each worker to receive.
                        channel.BasicQos(0, 2, false);

                        channel.QueueDeclare(queue: queue.Name,
                                             durable: queue.Durable,
                                             exclusive: queue.Exclusive,
                                             autoDelete: queue.AutoDelete);

                        var consumer       = new EventingBasicConsumer(channel);
                        consumer.Received += (model, evtArgs) =>
                        {
                            try
                            {
                                messageReceived.Invoke(model, evtArgs);
                                channel.BasicAck(evtArgs.DeliveryTag, false);
                            }
                            catch (Exception e)
                            {
                                channel.BasicNack(evtArgs.DeliveryTag, false, true);
                                exceptionReceived?.Invoke(model, evtArgs, e);
                                if (dieOnException)
                                {
                                    cancellationToken.Cancel();
                                    // TODO: find a better way to stop the thread instantaneosly
                                    // and not waiting for it to finish.
                                    Task.Delay(1 * 1000).Wait();
                                }
                            }
                        };

                        channel.BasicConsume(queue: queue.Name,
                                             autoAck: false,
                                             consumer: consumer);

                        // keep thread alive
                        while (!cancellationToken.IsCancellationRequested)
                        {
                            Task.Delay(1 * 1000).Wait();
                        }
                    }
            }, cancellationToken.Token);
        }