/// <summary> /// Starts asynchronous Azure queue multicast relaying of messages for the route, /// and immediately returns control. /// </summary> /// <returns></returns> public bool BeginAsyncMessageForwarding() { this.EndMessageForwarding(); if (this.SourceQueue.Queue == null) { this.LogWarning("Queue \"{0}\" failed to get initialized. Will not be polled.", this.SourceQueue.QueueName); return(false); } if (this.DestinationQueues.IsNullOrEmpty()) { this.LogInformation("Destination queues for source queue \"{0}\" are not specified. Source queue will not be polled.", this.SourceQueue.QueueName); return(false); } int initializedDestinationQueueCount = this.DestinationQueues.Count(destinationQueue => destinationQueue.Queue != null); this.LogInformation("Initialized {0} of {1} destination queues for source queue \"{2}\".", initializedDestinationQueueCount, this.DestinationQueues.Count, this.SourceQueue.QueueName); lock (this) { this.queueMonitor = this.InstantiateQueueMonitor(); } return(true); }
/// <summary> /// Stops route's message relay. /// </summary> public void EndMessageForwarding() { lock (this) { if (this.queueMonitor != null) { queueMonitor.Stop(); this.queueMonitor = null; } } }
/// <summary> /// Eliminates polling from getting a message off the regular Azure queue. /// Blocks until either messages arrive, or smart polling is terminated. /// Returns null if application is exiting or stop is signaled, otherwise non-empty collection of messages. /// Uses smart polling with delays between attempts to dequeue messages, ensuring lows CPU utilization and not leaking /// money for Azure storage transactions. /// </summary> /// <param name="queue">Azure queue to dequeue messages from.</param> /// <param name="messageInvisibilityTimeMillisec"> /// Time for queue element to be processed. If not deleted from queue within /// this time, message is automatically placed back in the queue. /// </param> /// <param name="maxCheckDelaySeconds">Maximum delay, in seconds, between attempts to dequeue messages.</param> /// <param name="useAopProxyWhenAccessingQueue"> /// Set to true to use Aspectacular AOP proxy with process-wide set of aspects, /// to call queue access functions. Set to false to call queue operations directly. /// </param> /// <returns>Returns null if application is exiting or stop is signaled, otherwise non-empty collection of messages.</returns> public static IList <CloudQueueMessage> WaitForMessages(this CloudQueue queue, int messageInvisibilityTimeMillisec, int maxCheckDelaySeconds = 60, bool useAopProxyWhenAccessingQueue = true) { if (queue == null) { throw new ArgumentNullException("queue"); } using (var qmon = new AzureQueuePicker(queue, messageInvisibilityTimeMillisec, maxCheckDelaySeconds, useAopProxyWhenAccessingQueue)) { IList <CloudQueueMessage> messages = qmon.WaitForPayload(); return(messages); } }
private AzureQueuePicker InstantiateQueueMonitor() { if (this.OptionalQueueMonitorInjector != null) { AzureQueuePicker qmon = this.OptionalQueueMonitorInjector(this); qmon.Subscribe(this.RelayMessages); return(qmon); } return(this.SourceQueue.Queue.Subscribe( this.RelayMessages, this.SourceQueue.MessageInivisibilityTimeMillisec, this.SourceQueue.MaxDelayBetweenDequeueAttemptsSeconds, useAopProxyWhenAccessingQueue: false )); }
/// <summary> /// Enable pub/sub pattern for regular Azure queues instead of polling by /// launching polling loop that invokes message-processing callback when messages arrived. /// This is an alternative to using blocking WaitForMessage() method. /// Uses smart polling with delays between attempts to dequeue messages, ensuring lows CPU utilization and not leaking /// money for Azure storage transactions. /// </summary> /// <param name="queue">Azure queue to dequeue messages from.</param> /// <param name="messageProcessCallback"> /// Optional message-processing delegate. If null, Process() method must be overridden /// in a subclass. /// </param> /// <param name="messageInvisibilityTimeMillisec"> /// Time for queue element to be processed. If not deleted from queue within /// this time, message is automatically placed back in the queue. /// </param> /// <param name="maxCheckDelaySeconds">Maximum delay, in seconds, between attempts to dequeue messages.</param> /// <param name="useAopProxyWhenAccessingQueue"> /// Set to true to use Aspectacular AOP proxy with process-wide set of aspects, /// to call queue access functions. Set to false to call queue operations directly. /// </param> /// <returns> /// IDisposable queue wrapper object to be used later for calling Stop() or Dispose() methods to terminate queue /// polling. /// </returns> /// <remarks> /// This method starts polling thread, on which both polling function and message processing functions are called. /// This means that next attempt to dequeue messages won't occur until message processing callback function is done. /// Payload processing callback may start its own thread(s) to process messages asynchronously and quickly return /// control to the polling thread. /// </remarks> public static AzureQueuePicker Subscribe(this CloudQueue queue, Action <CloudQueue, IList <CloudQueueMessage> > messageProcessCallback, int messageInvisibilityTimeMillisec, int maxCheckDelaySeconds = 60, bool useAopProxyWhenAccessingQueue = true) { if (queue == null) { throw new ArgumentNullException("queue"); } if (messageProcessCallback == null) { throw new ArgumentNullException("messageProcessCallback"); } var qmon = new AzureQueuePicker(queue, messageInvisibilityTimeMillisec, maxCheckDelaySeconds, useAopProxyWhenAccessingQueue); qmon.Subscribe(messageProcessCallback); return(qmon); }