/// <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)); }
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; }