/// <summary>
        /// Handles the <paramref name="message"/> from the queue trigger.
        /// </summary>
        /// <param name="message">The message to handle.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task HandleAsync(string message, CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrEmpty(message))
            {
                throw new ArgumentNullException(nameof(message));
            }

            var command = await _serializer.DeserializeAsync(message);

            await _processor.ProcessAsync(command, cancellationToken);
        }
            public BackgroundCommandEvent ToBackgroundCommandEvent(IBackgroundCommandSerializer serializer)
            {
                var status = BackgroundCommandEventStatus.Unknown;

                if (Enum.TryParse <BackgroundCommandEventStatus>(EventStatus, out var parsedStatus))
                {
                    status = parsedStatus;
                }

                Exception commandException = null;

                try
                {
                    if (!string.IsNullOrEmpty(Exception))
                    {
                        commandException = JsonConvert.DeserializeObject <Exception>(Exception);
                    }
                }
                catch
                {
                }

                return(new BackgroundCommandEvent(serializer.DeserializeAsync(Command).Result, status, EventTimestamp, commandException));
            }
Exemple #3
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var options = _options.Value;

            var processMessagesActionBlock = new ActionBlock <CloudQueueMessage>(
                async message =>
            {
                IBackgroundCommand command = null;
                try
                {
                    command = await _serializer.DeserializeAsync(message.AsString);

                    using (var handlerRuntimeCancellationTokenSource = new CancellationTokenSource(options.MaxHandlerRuntime))
                        using (var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, handlerRuntimeCancellationTokenSource.Token))
                            using (var scope = _services.CreateScope())
                            {
                                var processor = scope.ServiceProvider.GetRequiredService <IBackgroundProcessor>();
                                await processor.ProcessAsync(command, combinedCancellationTokenSource.Token);
                                await _queue.DeleteMessageAsync(message);
                            }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"An error occured while processing {command}: {ex.Message}", ex);
                }
            },
                new ExecutionDataflowBlockOptions
            {
                CancellationToken      = stoppingToken,
                BoundedCapacity        = options.DegreeOfParallelism,
                MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded,
            });

            var currentPollingFrequency = options.PollingFrequency;

            while (!stoppingToken.IsCancellationRequested)
            {
                var messages = await _queue.GetMessagesAsync(
                    messageCount : options.MessagesBatchSize,
                    visibilityTimeout : options.MaxHandlerRuntime.Add(options.HandlerCancellationGraceDelay),
                    options : options.QueueRequestOptions,
                    operationContext : options.OperationContextBuilder != null?options.OperationContextBuilder() : null);

                if (!messages.Any())
                {
                    await Task.Delay(currentPollingFrequency);

                    currentPollingFrequency = options.NextPollingFrequency(currentPollingFrequency);
                    continue;
                }

                currentPollingFrequency = options.PollingFrequency;

                foreach (var message in messages)
                {
                    await processMessagesActionBlock.SendAsync(message, stoppingToken);
                }
            }

            processMessagesActionBlock.Complete();
            await processMessagesActionBlock.Completion;
        }