public Result CreateQueue(string queueName, string exchangeToBind, string bindRoutingKey) { var res = new Result(); try { using (var connection = GetConnection(ServiceDescription + "_UtilService")) using (var channel = connection.CreateModel()) { RabbitMqUtilities.CreateQueueOrGetInfo(queueName, channel); var key = string.IsNullOrWhiteSpace(bindRoutingKey) ? string.Empty : bindRoutingKey; var exchange = string.IsNullOrWhiteSpace(exchangeToBind) ? string.Empty : exchangeToBind; if (!string.IsNullOrWhiteSpace(exchange)) { channel.QueueBind(queueName, exchange, key); } res.Success = true; } } catch (Exception e) { res.Success = false; res.ErrorDescription = e.Message; res.ErrorCode = -1; } return(res); }
/// <summary> /// StartConsumers - start consumers and connect them to a queue. /// </summary> /// <param name="consumerName">Consumer name</param> /// <param name="retryQueueDetails">Retry queue details if a message needs to be requeued with a delay (a Dead letter exchange must be defined)</param> /// <param name="queueName">Queue where the consumers will connect (optional - if not defined, the config value is used)</param> /// <param name="totalConsumers">Total consumers to start (optional - if not defined, the config value is used)</param> /// <param name="createQueue">Create queue to connect when starting consumers (optional - default is false)</param> /// <exception cref="RabbitMQClientException"></exception> public void StartConsumers(string consumerName, RetryQueueDetails retryQueueDetails, string queueName = null, byte?totalConsumers = null, bool createQueue = false) { var config = (IBrokerConfigConsumers)_config; var totalConsumersToStart = totalConsumers ?? config.TotalInstances; if (totalConsumersToStart <= 0) { throw new ArgumentException("Invalid total number of consumers to start"); } var triedCreateQueue = false; for (var i = 0; i < totalConsumersToStart; i++) { var routingKeyOrQueueName = string.IsNullOrWhiteSpace(queueName) ? config.RoutingKeyOrQueueName : queueName; var totalCreatedConsumers = _consumers.Count; var connection = GetConnection(ServiceDescription + "_" + i, totalCreatedConsumers, MaxChannelsPerConnection); var channel = connection.CreateModel(); if (createQueue && !triedCreateQueue) { try { RabbitMqUtilities.CreateQueueOrGetInfo(routingKeyOrQueueName, channel); triedCreateQueue = true; } catch (Exception e) { throw new RabbitMqClientException($"Unable do create queue. Details: {e.Message}", e); } } var consumer = new AsyncEventingBasicConsumerExtended(channel) { ConnectedToPort = connection.Endpoint.Port, ConnectedToHost = connection.Endpoint.HostName, ConnectionTime = DateTime.Now, Id = i, RetentionPeriodInRetryQueueMilliseconds = retryQueueDetails?.RetentionPeriodInRetryQueueMilliseconds ?? 0, RetentionPeriodInRetryQueueMillisecondsMax = retryQueueDetails?.RetentionPeriodInRetryQueueMillisecondsMax ?? 0, RetryQueue = retryQueueDetails?.RetryQueue }; consumer.Received += Consumer_Received; consumer.Shutdown += Consumer_Shutdown; var tag = $"{consumerName}_{i}"; consumer.ConsumerTag = tag; _consumers.Add(consumer); channel.BasicConsume(routingKeyOrQueueName, false, tag, consumer); } }
private async Task Consumer_Received(object sender, BasicDeliverEventArgs e) { var consumerTag = e.ConsumerTag; var routingKeyOrQueueName = e.RoutingKey; var exchange = e.Exchange; var message = ""; try { message = Encoding.UTF8.GetString(e.Body.Span.ToArray()); var consumer = (AsyncEventingBasicConsumerExtended)sender; consumer.LastMessageDate = DateTime.Now; var firstErrorTimestamp = RabbitMqUtilities.GetFirstErrorTimeStampFromMessageArgs(e.BasicProperties); var additionalInfo = RabbitMqUtilities.GetAdditionalInfoFromMessageArgs(e.BasicProperties); var model = consumer.Model; var messageProcessInstruction = await GetMessageProcessInstruction(routingKeyOrQueueName, consumerTag, firstErrorTimestamp, exchange, message, additionalInfo).ConfigureAwait(false); switch (messageProcessInstruction.Value) { case Constants.MessageProcessInstruction.OK: model.BasicAck(e.DeliveryTag, false); break; case Constants.MessageProcessInstruction.IgnoreMessage: model.BasicReject(e.DeliveryTag, false); break; case Constants.MessageProcessInstruction.IgnoreMessageWithRequeue: model.BasicReject(e.DeliveryTag, true); break; case Constants.MessageProcessInstruction.RequeueMessageWithDelay: RequeueMessageWithDelay(consumer, e, messageProcessInstruction.AdditionalInfo); model.BasicReject(e.DeliveryTag, false); break; default: model.BasicAck(e.DeliveryTag, false); break; } } catch (Exception ex) { await OnMessageReceiveError(routingKeyOrQueueName, consumerTag, exchange, message, ex.Message) .ConfigureAwait(false); } }
protected static void CreateQueue(string routingKeyOrQueueName, bool createQueue, string exchange, IModel channel) { if (string.IsNullOrWhiteSpace(exchange) && createQueue) { try { RabbitMqUtilities.CreateQueueOrGetInfo(routingKeyOrQueueName, channel); } catch (Exception e) { throw new RabbitMqClientException($"Unable do create queue. Details: {e.Message}", e); } } }
private void RequeueMessageWithDelay(AsyncEventingBasicConsumerExtended consumer, BasicDeliverEventArgs deliveryArgs, string messageAdditionalInfo) { if (string.IsNullOrWhiteSpace(consumer.RetryQueue)) { return; } var properties = consumer.Model.CreateBasicProperties(); RabbitMqUtilities.SetPropertiesSenderRequeueMessageWithDelay(properties, consumer.RetentionPeriodInRetryQueueMilliseconds, consumer.RetentionPeriodInRetryQueueMillisecondsMax); var firstErrorTimeStamp = RabbitMqUtilities.GetFirstErrorTimeStampFromMessageArgs(deliveryArgs.BasicProperties); SetFirstErrorTimeStampToProperties(firstErrorTimeStamp, properties); SetMessageAdditionalInfoToProperties(messageAdditionalInfo, properties); consumer.Model.BasicPublish( "", consumer.RetryQueue, properties, deliveryArgs.Body); }
protected void _Send(string exchangeName, string routingKeyOrQueueName, bool createQueue, IModel channel, string encodingName, IBrokerConfigSender config, byte[] body) { var properties = channel.CreateBasicProperties(); RabbitMqUtilities.SetPropertiesSender(properties, encodingName); var exchange = GetExchange(exchangeName, config); CreateQueue(routingKeyOrQueueName, createQueue, exchange, channel); var routingKey = GetRoutingKey(routingKeyOrQueueName, config); if (channel.IsClosed) { throw new Exception("Channel is closed"); } channel.BasicPublish( exchange, routingKey, properties, body); }