/// <summary> /// Initislizes a new instance of the <see cref="RestBusSubscriber"/> /// </summary> /// <param name="messageMapper">The <see cref="IMessageMapper"/> used by the subscriber.</param> /// <param name="settings">The subscriber settings</param> public RestBusSubscriber(IMessageMapper messageMapper, SubscriberSettings settings) { this.messageMapper = messageMapper; messagingConfig = messageMapper.MessagingConfig; //Fetched only once if (messagingConfig == null) throw new ArgumentException("messageMapper.MessagingConfig returned null", "messageMapper"); if (messageMapper.SupportedExchangeKinds == default(ExchangeKind)) { throw new ArgumentException("messageMapper.SupportedExchangeKinds is not set up.", "messageMapper"); } serviceName = (messageMapper.GetServiceName(null) ?? String.Empty).Trim(); subscriberIdHeader = new string[] { AmqpUtils.GetNewExclusiveQueueId() }; AmqpConnectionInfo.EnsureValid(messageMapper.ServerUris, "messageMapper.ServerUris"); this.connectionFactory = new ConnectionFactory(); connectionFactory.Uri = messageMapper.ServerUris[0].Uri; ConnectionNames = messageMapper.ServerUris.Select(u => u.FriendlyName ?? String.Empty).ToArray(); connectionFactory.RequestedHeartbeat = Client.RPCStrategyHelpers.HEART_BEAT; this.Settings = settings ?? new SubscriberSettings(); //Make sure a default value is set, if not supplied by user. this.Settings.Subscriber = this; //Indicate that the subcriber settings is owned by this subscriber. }
/// <summary> /// Initializes a new instance of the <see cref="T:RestBus.RabbitMQ.RestBusClient" /> class. /// </summary> /// <param name="messageMapper">The <see cref="IMessageMapper" /> the client uses to route messages.</param> /// <param name="settings">Client settings.</param> public RestBusClient(IMessageMapper messageMapper, ClientSettings settings ) : base(new HttpClientHandler(), true) { //Set default HttpClient related fields timeout = TimeSpan.FromSeconds(100); MaxResponseContentBufferSize = int.MaxValue; //TODO: Setup cancellation token here. //Ensure messageMapper server uris are valid AmqpConnectionInfo.EnsureValid(messageMapper.ServerUris, "messageMapper.ServerUris"); //Configure RestBus fields/properties this.messageMapper = messageMapper; this.messagingConfig = messageMapper.MessagingConfig; //Fetched only once. if (messagingConfig == null) throw new ArgumentException("messageMapper.MessagingConfig returned null"); //Set ClientSettings this.Settings = settings ?? new ClientSettings(); // Always have a default instance, if it wasn't passed in. this.Settings.Client = this; //Indicate that the settings is owned by this client. //Instantiate connection manager and RPC strategies; connectionMgr = new ConnectionManager(messageMapper.ServerUris); directStrategy = new DirectReplyToRPCStrategy(); callbackStrategy = new CallbackQueueRPCStrategy(this.Settings, messageMapper.GetServiceName(null)); }
//NOTE This is the only method that cannot be moved into RestBus.Common so keep that in mind if integrating other Amqp brokers public static void DeclareExchangeAndQueues(IModel channel, IMessageMapper messageMapper, MessagingConfiguration messagingConfig, string serviceName, object syncObject, string subscriberId ) { //TODO: IS the lock statement here necessary? lock (syncObject) { //TODO: Other Exchange types. string exchangeName = AmqpUtils.GetExchangeName(messagingConfig, serviceName, ExchangeKind.Direct); string workQueueName = AmqpUtils.GetWorkQueueName(messagingConfig, serviceName); if (serviceName != "") { //Declare direct exchange if (messageMapper.SupportedExchangeKinds.HasFlag(ExchangeKind.Direct)) { channel.ExchangeDeclare(exchangeName, AmqpUtils.GetExchangeKindName(ExchangeKind.Direct), messagingConfig.PersistentWorkQueuesAndExchanges, !messagingConfig.PersistentWorkQueuesAndExchanges, null); } } Dictionary<string, object> workQueueArgs = null; if (!messagingConfig.PersistentWorkQueuesAndExchanges) { workQueueArgs = new Dictionary<string, object>(); workQueueArgs.Add("x-expires", (long)AmqpUtils.GetWorkQueueExpiry().TotalMilliseconds); } //TODO: the line below can throw some kind of socket exception, so what do you do in that situation //Bear in mind that Restart may call this code. //The exception name is the OperationInterruptedException //Declare work queue channel.QueueDeclare(workQueueName, messagingConfig.PersistentWorkQueuesAndExchanges, false, false, workQueueArgs); channel.QueueBind(workQueueName, exchangeName, AmqpUtils.GetWorkQueueRoutingKey()); if(subscriberId != null) { string subscriberQueueName = AmqpUtils.GetSubscriberQueueName(serviceName, subscriberId); //The queue is set to be auto deleted once the last consumer stops using it. //However, RabbitMQ will not delete the queue if no consumer ever got to use it. //Passing x-expires in solves that: It tells RabbitMQ to delete the queue, if no one uses it within the specified time. var subscriberQueueArgs = new Dictionary<string, object>(); subscriberQueueArgs.Add("x-expires", (long)AmqpUtils.GetSubscriberQueueExpiry().TotalMilliseconds); //TODO: Look into making the subscriber queue exclusive //and retry with a different id if the queue has alreasy been taken. //in this case the Id property of the ISubscriber interface should be changed to GetId() //and will be documented to return the "current" id. //In fact Hide GetId and id property for both client and subscriber, they should be private for now. //Write something similar for the client. //TODO: the line below can throw some kind of socket exception, so what do you do in that situation //Bear in mind that Restart may call this code. //The exception name is the OperationInterruptedException //Declare subscriber queue channel.QueueDeclare(subscriberQueueName, false, false, true, subscriberQueueArgs); channel.QueueBind(subscriberQueueName, exchangeName, subscriberId); } } }
public static string GetExchangeName(MessagingConfiguration messagingConfig, string serviceName, ExchangeKind kind) { return exchangePrefix + serviceName + "." + GetExchangeKindName(kind) + (messagingConfig.PersistentWorkQueuesAndExchanges ? ".persistent" : String.Empty); }
public static string GetWorkQueueName(MessagingConfiguration messagingConfig, string serviceName) { return queuePrefix + PrefixSlashIfNotEmpty(serviceName) + workQueuePath + (messagingConfig.PersistentWorkQueuesAndExchanges ? "/persistent" : String.Empty); }