/// <summary> /// Sets the messenger up for either sending or receiving a specific message of type <typeparamref name="T"/>. /// This will create the <see cref="ServiceBusAdapter"/> but will not set it up for reading the queue. /// </summary> /// <typeparam name="T">The type of the message we are setting up.</typeparam> /// <param name="batchSize">The size of the batch when reading for a queue - used as the pre-fetch parameter of the <see cref="Microsoft.Azure.ServiceBus.Core.MessageReceiver"/>.</param> /// <param name="transport">The type of the transport to setup</param> /// <param name="topicName">Topic name to be used to create the topic. If not provided the type <typeparam name="T"/> will be used</param> /// <returns>The message queue adapter.</returns> internal ServiceBusAdapter <T> SetupMessageType <T>(int batchSize, MessagingTransport transport, string topicName) where T : class { ServiceBusAdapter adapter = null; if (!ServiceBusAdapters.ContainsKey(topicName)) { switch (transport) { case MessagingTransport.Queue: adapter = new QueueAdapter <T>(ConnectionString, SubscriptionId, MessagesIn.AsObserver(), batchSize, this); break; case MessagingTransport.Topic: adapter = new TopicAdapter <T>(ConnectionString, SubscriptionId, MessagesIn.AsObserver(), batchSize, this, topicName); break; default: throw new InvalidOperationException( $"The {nameof(MessagingTransport)} was extended and the use case on the {nameof(SetupMessageType)} switch wasn't."); } if (!ServiceBusAdapters.TryAdd(topicName, adapter)) { adapter.Dispose(); adapter = null; } } return((ServiceBusAdapter <T>)adapter ?? (ServiceBusAdapter <T>)ServiceBusAdapters[topicName]); }
/// <summary> /// Set up the required receive pipeline, for the given message type, and return a reactive <see cref="T:System.IObservable`1" /> that you can subscribe to. /// </summary> /// <typeparam name="T">The type of the message returned by the observable.</typeparam> /// <param name="batchSize">The size of the batch when reading from a queue.</param> /// <returns>The typed <see cref="T:System.IObservable`1" /> that you subscribed to.</returns> /// <exception cref="InvalidOperationException">ReceiverConfig must be set to read messages.</exception> public IObservable <T> StartReceive <T>(int batchSize = 10) where T : class { // Ensure config is setup. if (Config.ReceiverConfig == null) { throw new InvalidOperationException("Receiver configuration must be set"); } CreateIfNotExists(); _receiverClient ??= SubscriberClient.CreateAsync(new SubscriptionName(Config.ProjectId, Config.ReceiverConfig.ReadFromErrorEntity ? Config.ReceiverConfig.EntityDeadLetterName : Config.ReceiverConfig.EntitySubscriptionName), new SubscriberClient.ClientCreationSettings(credentials: GetCredentials())).GetAwaiter().GetResult(); IObserver <T> messageIn = _messagesIn.AsObserver(); _receiverClient.StartAsync((message, cancel) => { if (!cancel.IsCancellationRequested) { var typed = GetTypedMessageContent <T>(message); messageIn.OnNext(typed); } return(Task.FromResult(SubscriberClient.Reply.Ack)); }); return(_messagesIn.OfType <T>()); }
/// <summary> /// Starts the receive. /// </summary> /// <typeparam name="T">Type of object to receive</typeparam> /// <param name="batchSize">Size of message batches to receive in a single call. If set to zero, uses the default batch size from config.</param> /// <returns>IObservable{T}.</returns> public IObservable <T> StartReceive <T>(int batchSize = 10) where T : class { IObserver <T> obs = MessagesIn.AsObserver(); LockTimers.TryAdd(typeof(T), new Timer(t => { if (!_inBatch) { _inBatch = true; try { var msgItems = GetMessages <T>(batchSize).GetAwaiter().GetResult(); foreach (var msg in msgItems) { obs.OnNext(msg.Body); } } catch (Exception e) { obs.OnError(e); } finally { _inBatch = false; } } }, null, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500))); return(MessagesIn.OfType <T>().AsObservable()); }
/// <summary> /// Sets the messenger up for either sending or receiving a specific message of type <typeparamref name="T"/>. /// This will create the <see cref="Microsoft.ServiceBus.Messaging.QueueClient"/> but will not set it up for reading the queue. /// </summary> /// <typeparam name="T">The type of the message we are setting up.</typeparam> /// <returns>The message queue wrapper.</returns> internal MessageQueue <T> SetupMessageType <T>() where T : IMessage { lock (Gate) { if (!Queues.ContainsKey(typeof(T))) { var queue = new MessageQueue <T>(ConnectionString, MessagesIn.AsObserver()); Queues.Add(typeof(T), queue); } } return((MessageQueue <T>)Queues[typeof(T)]); }
/// <summary> /// Sets the messenger up for sending / receiving a specific message of type <typeparamref name="T" />. /// </summary> /// <typeparam name="T">The type of the message we are setting up.</typeparam> /// <returns>The message queue adapter.</returns> internal ServiceBusConnector <T> SetupConnectorType <T>() where T : class { Monitor.Enter(SetupGate); try { // If no adapter for this type already exists, then create an instance. if (!QueueConnectors.ContainsKey(typeof(T))) { var queue = new ServiceBusConnector <T>(ConnectionManager, MessagesIn.AsObserver(), Logger); QueueConnectors.TryAdd(typeof(T), queue); } return((ServiceBusConnector <T>)QueueConnectors[typeof(T)]); } finally { Monitor.Exit(SetupGate); } }