public QueueListener(IStorageQueue queue,
            IStorageQueue poisonQueue,
            ITriggerExecutor<IStorageQueueMessage> triggerExecutor,
            IDelayStrategy delayStrategy,
            IBackgroundExceptionDispatcher backgroundExceptionDispatcher,
            TraceWriter trace,
            SharedQueueWatcher sharedWatcher,
            IQueueConfiguration queueConfiguration)
        {
            if (trace == null)
            {
                throw new ArgumentNullException("trace");
            }

            if (queueConfiguration == null)
            {
                throw new ArgumentNullException("queueConfiguration");
            }

            if (queueConfiguration.BatchSize <= 0)
            {
                throw new ArgumentException("BatchSize must be greater than zero.");
            }

            if (queueConfiguration.MaxDequeueCount <= 0)
            {
                throw new ArgumentException("MaxDequeueCount must be greater than zero.");
            }

            _timer = new TaskSeriesTimer(this, backgroundExceptionDispatcher, Task.Delay(0));
            _queue = queue;
            _poisonQueue = poisonQueue;
            _triggerExecutor = triggerExecutor;
            _delayStrategy = delayStrategy;
            _backgroundExceptionDispatcher = backgroundExceptionDispatcher;
            _trace = trace;
            _queueConfiguration = queueConfiguration;

            if (sharedWatcher != null)
            {
                // Call Notify whenever a function adds a message to this queue.
                sharedWatcher.Register(queue.Name, this);
                _sharedWatcher = sharedWatcher;
            }

            EventHandler poisonMessageEventHandler = _sharedWatcher != null ? OnMessageAddedToPoisonQueue : (EventHandler)null;
            _queueProcessor = CreateQueueProcessor(
                _queue.SdkObject, _poisonQueue != null ? _poisonQueue.SdkObject : null,
                _trace, _queueConfiguration, poisonMessageEventHandler);
        }
        public UpdateQueueMessageVisibilityCommand(IStorageQueue queue, IStorageQueueMessage message,
            TimeSpan visibilityTimeout, IDelayStrategy speedupStrategy)
        {
            if (queue == null)
            {
                throw new ArgumentNullException("queue");
            }

            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (speedupStrategy == null)
            {
                throw new ArgumentNullException("speedupStrategy");
            }

            _queue = queue;
            _message = message;
            _visibilityTimeout = visibilityTimeout;
            _speedupStrategy = speedupStrategy;
        }
 public RenewLeaseCommand(IStorageBlockBlob leaseBlob, string leaseId, string lockId, IDelayStrategy speedupStrategy, TraceWriter trace)
 {
     _leaseBlob = leaseBlob;
     _leaseId = leaseId;
     _lockId = lockId;
     _speedupStrategy = speedupStrategy;
     _trace = trace;
 }
Пример #4
0
 public Reliable(IRetryStrategy retry, IDelayStrategy delay,
                 Action <Int32, Exception> retryHandler = null)
     : this(ToFunc(retry), ToFunc(delay, retryHandler))
 {
 }
Пример #5
0
 public Reliable(Func <Exception, Boolean> retry, IDelayStrategy delay,
                 Action <Int32, Exception> retryHandler = null)
     : this(retry, ToFunc(delay, retryHandler))
 {
 }
 public RecurrentTaskSeriesCommand(IRecurrentCommand innerCommand, IDelayStrategy delayStrategy)
 {
     _innerCommand  = innerCommand;
     _delayStrategy = delayStrategy;
 }
Пример #7
0
 public RenewLeaseCommand(IStorageBlockBlob leaseBlob, string leaseId, string lockId, IDelayStrategy speedupStrategy, TraceWriter trace,
                          ILogger logger, TimeSpan leasePeriod)
 {
     _lastRenewal     = DateTimeOffset.UtcNow;
     _leaseBlob       = leaseBlob;
     _leaseId         = leaseId;
     _lockId          = lockId;
     _speedupStrategy = speedupStrategy;
     _trace           = trace;
     _logger          = logger;
     _leasePeriod     = leasePeriod;
 }
 public RecurrentTaskSeriesCommand(IRecurrentCommand innerCommand, IDelayStrategy delayStrategy)
 {
     _innerCommand = innerCommand;
     _delayStrategy = delayStrategy;
 }
Пример #9
0
        public QueueListener(CloudQueue queue,
                             CloudQueue poisonQueue,
                             ITriggerExecutor <CloudQueueMessage> triggerExecutor,
                             IWebJobsExceptionHandler exceptionHandler,
                             ILoggerFactory loggerFactory,
                             SharedQueueWatcher sharedWatcher,
                             QueuesOptions queueOptions,
                             IQueueProcessorFactory queueProcessorFactory,
                             TimeSpan?maxPollingInterval = null)
        {
            if (queueOptions == null)
            {
                throw new ArgumentNullException(nameof(queueOptions));
            }

            if (queueProcessorFactory == null)
            {
                throw new ArgumentNullException(nameof(queueProcessorFactory));
            }

            if (queueOptions.BatchSize <= 0)
            {
                throw new ArgumentException("BatchSize must be greater than zero.");
            }

            if (queueOptions.MaxDequeueCount <= 0)
            {
                throw new ArgumentException("MaxDequeueCount must be greater than zero.");
            }

            _timer            = new TaskSeriesTimer(this, exceptionHandler, Task.Delay(0));
            _queue            = queue;
            _poisonQueue      = poisonQueue;
            _triggerExecutor  = triggerExecutor;
            _exceptionHandler = exceptionHandler;
            _queueOptions     = queueOptions;

            // if the function runs longer than this, the invisibility will be updated
            // on a timer periodically for the duration of the function execution
            _visibilityTimeout = TimeSpan.FromMinutes(10);

            if (sharedWatcher != null)
            {
                // Call Notify whenever a function adds a message to this queue.
                sharedWatcher.Register(queue.Name, this);
                _sharedWatcher = sharedWatcher;
            }

            EventHandler <PoisonMessageEventArgs> poisonMessageEventHandler = _sharedWatcher != null ? OnMessageAddedToPoisonQueue : (EventHandler <PoisonMessageEventArgs>)null;

            _queueProcessor = CreateQueueProcessor(_queue, _poisonQueue, loggerFactory, queueProcessorFactory, _queueOptions, poisonMessageEventHandler);

            TimeSpan maximumInterval = _queueProcessor.MaxPollingInterval;

            if (maxPollingInterval.HasValue && maximumInterval > maxPollingInterval.Value)
            {
                // enforce the maximum polling interval if specified
                maximumInterval = maxPollingInterval.Value;
            }

            _delayStrategy = new RandomizedExponentialBackoffStrategy(QueuePollingIntervals.Minimum, maximumInterval);
        }
Пример #10
0
        public QueueListener(QueueClient queue,
                             QueueClient poisonQueue,
                             ITriggerExecutor <QueueMessage> triggerExecutor,
                             IWebJobsExceptionHandler exceptionHandler,
                             ILoggerFactory loggerFactory,
                             SharedQueueWatcher sharedWatcher,
                             QueuesOptions queueOptions,
                             IQueueProcessorFactory queueProcessorFactory,
                             FunctionDescriptor functionDescriptor,
                             string functionId           = null,
                             TimeSpan?maxPollingInterval = null)
        {
            if (queueOptions == null)
            {
                throw new ArgumentNullException(nameof(queueOptions));
            }

            if (queueProcessorFactory == null)
            {
                throw new ArgumentNullException(nameof(queueProcessorFactory));
            }

            if (loggerFactory == null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            if (queueOptions.BatchSize <= 0)
            {
                throw new ArgumentException("BatchSize must be greater than zero.");
            }

            if (queueOptions.MaxDequeueCount <= 0)
            {
                throw new ArgumentException("MaxDequeueCount must be greater than zero.");
            }

            _timer              = new TaskSeriesTimer(this, exceptionHandler, Task.Delay(0));
            _queue              = queue;
            _poisonQueue        = poisonQueue;
            _triggerExecutor    = triggerExecutor;
            _exceptionHandler   = exceptionHandler;
            _queueOptions       = queueOptions;
            _logger             = loggerFactory.CreateLogger <QueueListener>();
            _functionDescriptor = functionDescriptor ?? throw new ArgumentNullException(nameof(functionDescriptor));
            _functionId         = functionId ?? _functionDescriptor.Id;

            // if the function runs longer than this, the invisibility will be updated
            // on a timer periodically for the duration of the function execution
            _visibilityTimeout = TimeSpan.FromMinutes(10);

            if (sharedWatcher != null)
            {
                // Call Notify whenever a function adds a message to this queue.
                sharedWatcher.Register(queue.Name, this);
                _sharedWatcher = sharedWatcher;
            }

            EventHandler <PoisonMessageEventArgs> poisonMessageEventHandler = _sharedWatcher != null ? OnMessageAddedToPoisonQueue : (EventHandler <PoisonMessageEventArgs>)null;

            _queueProcessor = CreateQueueProcessor(_queue, _poisonQueue, loggerFactory, queueProcessorFactory, _queueOptions, poisonMessageEventHandler);

            TimeSpan maximumInterval = _queueProcessor.MaxPollingInterval;

            if (maxPollingInterval.HasValue && maximumInterval > maxPollingInterval.Value)
            {
                // enforce the maximum polling interval if specified
                maximumInterval = maxPollingInterval.Value;
            }

            _delayStrategy = new RandomizedExponentialBackoffStrategy(SharedQueuePollingIntervals.Minimum, maximumInterval);

            _scaleMonitorDescriptor          = new ScaleMonitorDescriptor($"{_functionId}-QueueTrigger-{_queue.Name}".ToLower(CultureInfo.InvariantCulture));
            _shutdownCancellationTokenSource = new CancellationTokenSource();
        }
Пример #11
0
 public RenewLeaseCommand(IStorageBlockBlob leaseBlob, string leaseId, string lockId, IDelayStrategy speedupStrategy, TraceWriter trace)
 {
     _leaseBlob       = leaseBlob;
     _leaseId         = leaseId;
     _lockId          = lockId;
     _speedupStrategy = speedupStrategy;
     _trace           = trace;
 }
Пример #12
0
 public RenewLeaseCommand(IDistributedLockManager lockManager, IDistributedLock @lock, IDelayStrategy speedupStrategy)
 {
     _lock            = @lock;
     _lockManager     = lockManager;
     _speedupStrategy = speedupStrategy;
 }
Пример #13
0
        /// <summary>
        /// Tries to execute the operation provided by the <see cref="ExecuteOperation"/> event several times.
        /// </summary>
        /// <param name="maxRetryAttempts">The maximum number of allowed retry attempts.</param>
        /// <param name="delayStrategy">Strategy to provide delay between two retry attempts.</param>
        /// <returns>True if operation was executed successfully before the maximum number of retry attempts is reached; otherwise, false.</returns>
        /// <exception cref="ArgumentOutOfRangeException">Parameter <paramref name="maxRetryAttempts"/> is less than or equal to zero.</exception>
        /// <exception cref="ArgumentNullException">Parameter <paramref name="delayStrategy"/> is null.</exception>
        /// <exception cref="InvalidOperationException">There is no subscription for the <see cref="ExecuteOperation"/> event.</exception>
        /// <remarks>
        /// Tries to execute the operation by raising the <see cref="ExecuteOperation"/> event.
        /// If it fails, a new attempt is made after delay provided by the specified delay strategy.
        /// When the first time operation succeeds method returns true.
        /// If the maximum number of attempts is reached, method returns false.
        /// </remarks>
        public bool Execute(int maxRetryAttempts, IDelayStrategy delayStrategy)
        {
            if (maxRetryAttempts <= 0)
            {
                throw new ArgumentOutOfRangeException("maxRetryAttempts", maxRetryAttempts, "Max retry attempts must be a positive number.");
            }

            if (delayStrategy == null)
            {
                throw new ArgumentNullException("delayStrategy");
            }

            if (this.ExecuteOperation == null)
            {
                throw new InvalidOperationException("Execute operation is not specified.");
            }

            int failedRetriesCount = 0;

            Exception lastError;

            EventHandler <RetryableOperationFailedEventArgs> failedEventHandler;

            while (true)
            {
                lastError = null;

                try
                {
                    RetryableOperationEventArgs args = new RetryableOperationEventArgs(failedRetriesCount)
                    {
                        Success = true
                    };

                    this.ExecuteOperation(this, args);

                    if (args.Success)
                    {
                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    if (ex.IsCritical())
                    {
                        throw;
                    }

                    lastError = ex;
                }

                failedRetriesCount++;

                if (failedRetriesCount == maxRetryAttempts)
                {
                    return(false);
                }

                failedEventHandler = this.RetryFailed;

                if (failedEventHandler != null)
                {
                    failedEventHandler(this, new RetryableOperationFailedEventArgs(failedRetriesCount, lastError));
                }

                var delay = delayStrategy.NextDelay();

                Thread.Sleep(delay);
            }
        }