public void TestVerifyPopulatedChecks() { var producerOptions = new ProducerOptions(); Assert.False(producerOptions.VerifyPopulated()); producerOptions.ExchangeName = ""; Assert.False(producerOptions.VerifyPopulated()); producerOptions.ExchangeName = "Test.ExchangeName"; Assert.True(producerOptions.VerifyPopulated()); var consumerOptions = new ConsumerOptions(); Assert.False(consumerOptions.VerifyPopulated()); consumerOptions.QueueName = "Test.QueueName"; Assert.False(consumerOptions.VerifyPopulated()); consumerOptions.QoSPrefetchCount = 1234; Assert.True(consumerOptions.VerifyPopulated()); }
/// <summary> /// Setup a subscription to a queue which sends messages to the <see cref="IConsumer"/>. /// </summary> /// <param name="consumerOptions">The connection options.</param> /// <param name="consumer">Consumer that will be sent any received messages.</param> /// <param name="isSolo">If specified, will ensure that it is the only consumer on the provided queue</param> /// <returns>Identifier for the consumer task, can be used to stop the consumer without shutting down the whole adapter</returns> public Guid StartConsumer(ConsumerOptions consumerOptions, IConsumer consumer, bool isSolo = false) { if (ShutdownCalled) { throw new ApplicationException("Adapter has been shut down"); } if (consumerOptions == null) { throw new ArgumentNullException(nameof(consumerOptions)); } if (!consumerOptions.VerifyPopulated()) { throw new ArgumentException("The given ConsumerOptions has invalid values"); } // Client label is the same for the IConnection and Subscription since we have a separate connection per consumer string label = string.Format("{0}::Consumer::{1}", _hostId, consumerOptions.QueueName); IConnection connection = _factory.CreateConnection(label); connection.ConnectionBlocked += (s, a) => _logger.Warn($"ConnectionBlocked for {consumerOptions.QueueName} ( Reason: {a.Reason})"); connection.ConnectionUnblocked += (s, a) => _logger.Warn($"ConnectionUnblocked for {consumerOptions.QueueName}"); IModel model = connection.CreateModel(); model.BasicQos(0, consumerOptions.QoSPrefetchCount, false); // Check queue exists try { // Passively declare the queue (equivalent to checking the queue exists) model.QueueDeclarePassive(consumerOptions.QueueName); } catch (OperationInterruptedException e) { model.Close(200, "StartConsumer - Queue missing"); connection.Close(200, "StartConsumer - Queue missing"); throw new ApplicationException($"Expected queue \"{consumerOptions.QueueName}\" to exist", e); } if (isSolo && model.ConsumerCount(consumerOptions.QueueName) > 0) { model.Close(200, "StartConsumer - Already a consumer on the queue"); connection.Close(200, "StartConsumer - Already a consumer on the queue"); throw new ApplicationException($"Already a consumer on queue {consumerOptions.QueueName} and solo consumer was specified"); } Subscription subscription = null; var connected = false; var failed = 0; while (!connected) { try { subscription = new Subscription(model, consumerOptions.QueueName, consumerOptions.AutoAck, label); connected = true; } catch (TimeoutException) { if (++failed >= MaxSubscriptionAttempts) { _logger.Warn("Retries exceeded, throwing exception"); throw; } _logger.Warn($"Timeout when creating Subscription, retrying in 5s..."); Thread.Sleep(TimeSpan.FromSeconds(5)); } catch (OperationInterruptedException e) { throw new ApplicationException( $"Error when creating subscription on queue \"{consumerOptions.QueueName}\"", e); } finally { if (!connected) { model.Close(200, "StartConsumer - Couldn't create subscription"); connection.Close(200, "StartConsumer - Couldn't create subscription"); } } } Guid taskId = Guid.NewGuid(); var taskTokenSource = new CancellationTokenSource(); var consumerTask = new Task(() => Consume(subscription, consumer, taskTokenSource.Token)); var resources = new ConsumerResources { Connection = connection, Model = model, Subscription = subscription, ConsumerTask = consumerTask, TokenSource = taskTokenSource }; lock (_oResourceLock) { _rabbitResources.Add(taskId, resources); } consumer.OnFatal += (s, e) => { resources.Shutdown(DefaultOperationTimeout); _hostFatalHandler(s, e); }; consumerTask.Start(); _logger.Debug($"Consumer task started [QueueName={subscription?.QueueName}]"); return(taskId); }