public ConnectionFactoryWrapper(ConnectionConfiguration connectionConfiguration, IClusterHostSelectionStrategy <ConnectionFactoryInfo> clusterHostSelectionStrategy)
        {
            this.clusterHostSelectionStrategy = clusterHostSelectionStrategy;

            Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");
            Preconditions.CheckAny(connectionConfiguration.Hosts, "connectionConfiguration", "At least one host must be defined in connectionConfiguration");

            Configuration = connectionConfiguration;

            foreach (var hostConfiguration in Configuration.Hosts)
            {
                var connectionFactory = new ConnectionFactory
                {
                    UseBackgroundThreadsForIO = connectionConfiguration.UseBackgroundThreads,
                    AutomaticRecoveryEnabled  = false,
                    TopologyRecoveryEnabled   = false
                };

                if (connectionConfiguration.AMQPConnectionString != null)
                {
                    connectionFactory.Uri = connectionConfiguration.AMQPConnectionString;
                }

                connectionFactory.HostName = hostConfiguration.Host;

                if (connectionFactory.VirtualHost == "/")
                {
                    connectionFactory.VirtualHost = Configuration.VirtualHost;
                }

                if (connectionFactory.UserName == "guest")
                {
                    connectionFactory.UserName = Configuration.UserName;
                }

                if (connectionFactory.Password == "guest")
                {
                    connectionFactory.Password = Configuration.Password;
                }

                if (connectionFactory.Port == -1)
                {
                    connectionFactory.Port = hostConfiguration.Port;
                }

                if (hostConfiguration.Ssl.Enabled)
                {
                    connectionFactory.Ssl = hostConfiguration.Ssl;
                }

                //Prefer SSL configurations per each host but fall back to ConnectionConfiguration's SSL configuration for backwards compatibility
                else if (Configuration.Ssl.Enabled)
                {
                    connectionFactory.Ssl = Configuration.Ssl;
                }

                connectionFactory.RequestedHeartbeat = TimeSpan.FromSeconds(Configuration.RequestedHeartbeat);
                connectionFactory.ClientProperties   = Configuration.ClientProperties;
                connectionFactory.AuthMechanisms     = Configuration.AuthMechanisms;
                clusterHostSelectionStrategy.Add(new ConnectionFactoryInfo(connectionFactory, hostConfiguration));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Set the container creation function. This allows you to replace EasyNetQ's default internal
        /// IoC container. Note that all components should be registered as singletons. EasyNetQ will
        /// also call Dispose on components that are no longer required.
        /// </summary>
        public static void SetContainerFactory(Func <IContainer> createContainer)
        {
            Preconditions.CheckNotNull(createContainer, "createContainer");

            createContainerInternal = createContainer;
        }
Beispiel #3
0
        /// <summary>
        /// Creates a new instance of RabbitBus.
        /// </summary>
        /// <param name="connectionString">
        /// The EasyNetQ connection string. Example:
        /// host=192.168.1.1;port=5672;virtualHost=MyVirtualHost;username=MyUsername;password=MyPassword;requestedHeartbeat=10
        ///
        /// The following default values will be used if not specified:
        /// host=localhost;port=5672;virtualHost=/;username=guest;password=guest;requestedHeartbeat=0
        /// </param>
        /// <returns>
        /// A new RabbitBus instance.
        /// </returns>
        public static IBus CreateBus(string connectionString)
        {
            Preconditions.CheckNotNull(connectionString, "connectionString");

            return(CreateBus(connectionString, x => {}));
        }
Beispiel #4
0
        public void Publish <T>(T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");

            PublishAsync(message).Wait();
        }
Beispiel #5
0
        public Task PublishAsync <T>(T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");

            return(PublishAsync(message, conventions.TopicNamingConvention(typeof(T))));
        }
        /// <summary>
        /// Publishes a message with a topic.
        /// When used with publisher confirms the task completes when the publish is confirmed.
        /// Task will throw an exception if the confirm is NACK'd or times out.
        /// </summary>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="messageType">The message type</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns></returns>
        public static Task PublishAsync(this IPubSub pubSub, object message, Type messageType, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            return(pubSub.PublishAsync(message, messageType, c => { }, cancellationToken));
        }
Beispiel #7
0
        public virtual void Publish <T>(T message) where T : class
        {
            Preconditions.CheckNotNull(message, "message");

            Publish(message, conventions.TopicNamingConvention(typeof(T)));
        }
Beispiel #8
0
        public async Task <IQueue> QueueDeclareAsync(
            string name,
            bool passive                = false,
            bool durable                = true,
            bool exclusive              = false,
            bool autoDelete             = false,
            int?perQueueMessageTtl      = null,
            int?expires                 = null,
            int?maxPriority             = null,
            string deadLetterExchange   = null,
            string deadLetterRoutingKey = null,
            int?maxLength               = null,
            int?maxLengthBytes          = null)
        {
            Preconditions.CheckNotNull(name, "name");

            if (passive)
            {
                await clientCommandDispatcher.InvokeAsync(x => x.QueueDeclarePassive(name)).ConfigureAwait(false);

                return(new Queue(name, exclusive));
            }

            var arguments = new Dictionary <string, object>();

            if (perQueueMessageTtl.HasValue)
            {
                arguments.Add("x-message-ttl", perQueueMessageTtl.Value);
            }
            if (expires.HasValue)
            {
                arguments.Add("x-expires", expires);
            }
            if (maxPriority.HasValue)
            {
                arguments.Add("x-max-priority", maxPriority.Value);
            }
            // Allow empty dead-letter-exchange as it represents the default rabbitmq exchange
            // and thus is a valid value. To dead-letter a message directly to a queue, you
            // would set dead-letter-exchange to empty and dead-letter-routing-key to name of the
            // queue since every queue has a direct binding with default exchange.
            if (deadLetterExchange != null)
            {
                arguments.Add("x-dead-letter-exchange", deadLetterExchange);
            }
            if (!string.IsNullOrEmpty(deadLetterRoutingKey))
            {
                arguments.Add("x-dead-letter-routing-key", deadLetterRoutingKey);
            }
            if (maxLength.HasValue)
            {
                arguments.Add("x-max-length", maxLength.Value);
            }
            if (maxLengthBytes.HasValue)
            {
                arguments.Add("x-max-length-bytes", maxLengthBytes.Value);
            }

            await clientCommandDispatcher.InvokeAsync(x => x.QueueDeclare(name, durable, exclusive, autoDelete, arguments)).ConfigureAwait(false);

            logger.DebugWrite("Declared Queue: '{0}', durable:{1}, exclusive:{2}, autoDelete:{3}, args:{4}", name, durable, exclusive, autoDelete, string.Join(", ", arguments.Select(kvp =>
                                                                                                                                                                                      $"{kvp.Key}={kvp.Value}")));
            return(new Queue(name, exclusive));
        }
        /// <summary>
        /// Publishes a message.
        /// </summary>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="messageType">The message type</param>
        /// <param name="cancellationToken">The cancellation token</param>
        public static void Publish(this IPubSub pubSub, object message, Type messageType, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            pubSub.Publish(message, messageType, c => { }, cancellationToken);
        }
Beispiel #10
0
        public virtual async Task PublishAsync(
            IExchange exchange,
            string routingKey,
            bool mandatory,
            MessageProperties messageProperties,
            byte[] body)
        {
            Preconditions.CheckNotNull(exchange, "exchange");
            Preconditions.CheckShortString(routingKey, "routingKey");
            Preconditions.CheckNotNull(messageProperties, "messageProperties");
            Preconditions.CheckNotNull(body, "body");

            // Fix me: It's very hard now to move publish logic to separate abstraction, just leave it here.
            var rawMessage = produceConsumeInterceptor.OnProduce(new RawMessage(messageProperties, body));

            if (connectionConfiguration.PublisherConfirms)
            {
                var timeBudget = new TimeBudget(TimeSpan.FromSeconds(connectionConfiguration.Timeout)).Start();
                while (!timeBudget.IsExpired())
                {
                    var confirmsWaiter = await clientCommandDispatcher.InvokeAsync(model =>
                    {
                        var properties = model.CreateBasicProperties();
                        rawMessage.Properties.CopyTo(properties);
                        var waiter = confirmationListener.GetWaiter(model);

                        try
                        {
                            model.BasicPublish(exchange.Name, routingKey, mandatory, properties, rawMessage.Body);
                        }
                        catch (Exception)
                        {
                            waiter.Cancel();
                            throw;
                        }

                        return(waiter);
                    }).ConfigureAwait(false);

                    try
                    {
                        await confirmsWaiter.WaitAsync(timeBudget.GetRemainingTime()).ConfigureAwait(false);

                        break;
                    }
                    catch (PublishInterruptedException)
                    {
                    }
                }
            }
            else
            {
                await clientCommandDispatcher.InvokeAsync(model =>
                {
                    var properties = model.CreateBasicProperties();
                    rawMessage.Properties.CopyTo(properties);
                    model.BasicPublish(exchange.Name, routingKey, mandatory, properties, rawMessage.Body);
                }).ConfigureAwait(false);
            }
            eventBus.Publish(new PublishedMessageEvent(exchange.Name, routingKey, rawMessage.Properties, rawMessage.Body));
            logger.DebugWrite("Published to exchange: '{0}', routing key: '{1}', correlationId: '{2}'", exchange.Name, routingKey, messageProperties.CorrelationId);
        }
Beispiel #11
0
        public RabbitAdvancedBus(
            IConnectionFactory connectionFactory,
            IConsumerFactory consumerFactory,
            IEasyNetQLogger logger,
            IClientCommandDispatcherFactory clientCommandDispatcherFactory,
            IPublishConfirmationListener confirmationListener,
            IEventBus eventBus,
            IHandlerCollectionFactory handlerCollectionFactory,
            IContainer container,
            ConnectionConfiguration connectionConfiguration,
            IProduceConsumeInterceptor produceConsumeInterceptor,
            IMessageSerializationStrategy messageSerializationStrategy,
            IConventions conventions,
            AdvancedBusEventHandlers advancedBusEventHandlers,
            IPersistentConnectionFactory persistentConnectionFactory)
        {
            Preconditions.CheckNotNull(connectionFactory, "connectionFactory");
            Preconditions.CheckNotNull(consumerFactory, "consumerFactory");
            Preconditions.CheckNotNull(logger, "logger");
            Preconditions.CheckNotNull(eventBus, "eventBus");
            Preconditions.CheckNotNull(handlerCollectionFactory, "handlerCollectionFactory");
            Preconditions.CheckNotNull(container, "container");
            Preconditions.CheckNotNull(messageSerializationStrategy, "messageSerializationStrategy");
            Preconditions.CheckNotNull(connectionConfiguration, "connectionConfiguration");
            Preconditions.CheckNotNull(produceConsumeInterceptor, "produceConsumeInterceptor");
            Preconditions.CheckNotNull(conventions, "conventions");
            Preconditions.CheckNotNull(advancedBusEventHandlers, "advancedBusEventHandlers");
            Preconditions.CheckNotNull(persistentConnectionFactory, "persistentConnectionFactory");

            this.consumerFactory              = consumerFactory;
            this.logger                       = logger;
            this.confirmationListener         = confirmationListener;
            this.eventBus                     = eventBus;
            this.handlerCollectionFactory     = handlerCollectionFactory;
            this.Container                    = container;
            this.connectionConfiguration      = connectionConfiguration;
            this.produceConsumeInterceptor    = produceConsumeInterceptor;
            this.messageSerializationStrategy = messageSerializationStrategy;
            this.Conventions                  = conventions;

            this.eventBus.Subscribe <ConnectionCreatedEvent>(e => OnConnected());
            if (advancedBusEventHandlers.Connected != null)
            {
                Connected += advancedBusEventHandlers.Connected;
            }
            this.eventBus.Subscribe <ConnectionDisconnectedEvent>(e => OnDisconnected());
            if (advancedBusEventHandlers.Disconnected != null)
            {
                Disconnected += advancedBusEventHandlers.Disconnected;
            }
            this.eventBus.Subscribe <ConnectionBlockedEvent>(OnBlocked);
            if (advancedBusEventHandlers.Blocked != null)
            {
                Blocked += advancedBusEventHandlers.Blocked;
            }
            this.eventBus.Subscribe <ConnectionUnblockedEvent>(e => OnUnblocked());
            if (advancedBusEventHandlers.Unblocked != null)
            {
                Unblocked += advancedBusEventHandlers.Unblocked;
            }
            this.eventBus.Subscribe <ReturnedMessageEvent>(OnMessageReturned);
            if (advancedBusEventHandlers.MessageReturned != null)
            {
                MessageReturned += advancedBusEventHandlers.MessageReturned;
            }

            connection = persistentConnectionFactory.CreateConnection();
            clientCommandDispatcher = clientCommandDispatcherFactory.GetClientCommandDispatcher(connection);
            connection.Initialize();
        }
Beispiel #12
0
        /// <summary>
        /// Publishes a message with a topic
        /// </summary>
        /// <typeparam name="T">The message type</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="topic">The topic string</param>
        /// <param name="cancellationToken">The cancellation token</param>
        public static void Publish <T>(this IPubSub pubSub, T message, string topic, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            pubSub.Publish(message, c => c.WithTopic(topic), cancellationToken);
        }
Beispiel #13
0
        /// <summary>
        /// Creates a new instance of <see cref="RabbitBus"/>.
        /// </summary>
        /// <param name="connectionString">
        /// The EasyNetQ connection string. Example:
        /// host=192.168.1.1;port=5672;virtualHost=MyVirtualHost;username=MyUsername;password=MyPassword;requestedHeartbeat=10
        /// 
        /// The following default values will be used if not specified:
        /// host=localhost;port=5672;virtualHost=/;username=guest;password=guest;requestedHeartbeat=10
        /// </param>
        /// <returns>
        /// A new <see cref="RabbitBus"/> instance.
        /// </returns>
        public static IBus CreateBus(string connectionString)
        {
            Preconditions.CheckNotNull(connectionString, "connectionString");

            return CreateBus(connectionString, AdvancedBusEventHandlers.Default);
        }
Beispiel #14
0
        public virtual IQueue QueueDeclare(
            string name,
            bool passive                = false,
            bool durable                = true,
            bool exclusive              = false,
            bool autoDelete             = false,
            int?perQueueMessageTtl      = null,
            int?expires                 = null,
            int?maxPriority             = null,
            string deadLetterExchange   = null,
            string deadLetterRoutingKey = null,
            int?maxLength               = null,
            int?maxLengthBytes          = null)
        {
            Preconditions.CheckNotNull(name, "name");

            if (passive)
            {
                clientCommandDispatcher.Invoke(x => x.QueueDeclarePassive(name));
                return(new Queue(name, exclusive));
            }

            var arguments = new Dictionary <string, object>();

            if (perQueueMessageTtl.HasValue)
            {
                arguments.Add("x-message-ttl", perQueueMessageTtl.Value);
            }
            if (expires.HasValue)
            {
                arguments.Add("x-expires", expires);
            }
            if (maxPriority.HasValue)
            {
                arguments.Add("x-max-priority", maxPriority.Value);
            }
            // Allow empty dead-letter-exchange as it represents the default rabbitmq exchange
            // and thus is a valid value. To dead-letter a message directly to a queue, you
            // would set dead-letter-exchange to empty and dead-letter-routing-key to name of the
            // queue since every queue has a direct binding with default exchange.
            if (deadLetterExchange != null)
            {
                arguments.Add("x-dead-letter-exchange", deadLetterExchange);
            }
            if (!string.IsNullOrEmpty(deadLetterRoutingKey))
            {
                arguments.Add("x-dead-letter-routing-key", deadLetterRoutingKey);
            }
            if (maxLength.HasValue)
            {
                arguments.Add("x-max-length", maxLength.Value);
            }
            if (maxLengthBytes.HasValue)
            {
                arguments.Add("x-max-length-bytes", maxLengthBytes.Value);
            }

            var queueDeclareOk = clientCommandDispatcher.Invoke(x => x.QueueDeclare(name, durable, exclusive, autoDelete, arguments));

            if (logger.IsDebugEnabled())
            {
                logger.DebugFormat(
                    "Declared queue {queue}: durable={durable}, exclusive={exclusive}, autoDelete={autoDelete}, arguments={arguments}",
                    queueDeclareOk.QueueName,
                    durable,
                    exclusive,
                    autoDelete,
                    arguments.Stringify()
                    );
            }

            return(new Queue(queueDeclareOk.QueueName, exclusive));
        }