private async Task UpdateMessageVisibilityTimeout( IQueueMessageContext messageContext, Message typedMessage, Exception lastException, CancellationToken cancellationToken) { if (TryGetApproxReceiveCount(messageContext.Message.Attributes, out int approxReceiveCount)) { var visibilityTimeout = _messageBackoffStrategy.GetBackoffDuration(typedMessage, approxReceiveCount, lastException); try { await messageContext.ChangeMessageVisibilityAsync(visibilityTimeout, cancellationToken) .ConfigureAwait(false); } catch (AmazonServiceException ex) { _logger.LogError( ex, "Failed to update message visibility timeout by {VisibilityTimeout} seconds for message with receipt handle '{ReceiptHandle}'.", visibilityTimeout, messageContext.Message.ReceiptHandle); _messagingMonitor.HandleError(ex, messageContext.Message); } } }
DeserializeMessage(IQueueMessageContext messageContext, CancellationToken cancellationToken) { try { var messageWithAttributes = _serializationRegister.DeserializeMessage(messageContext.Message.Body); return(true, messageWithAttributes.Message, messageWithAttributes.MessageAttributes); } catch (MessageFormatNotSupportedException ex) { _logger.LogTrace( "Could not handle message with Id '{MessageId}' because a deserializer for the content is not configured. Message body: '{MessageBody}'.", messageContext.Message.MessageId, messageContext.Message.Body); await messageContext.DeleteMessageFromQueueAsync(cancellationToken).ConfigureAwait(false); _messagingMonitor.HandleError(ex, messageContext.Message); return(false, null, null); } #pragma warning disable CA1031 catch (Exception ex) #pragma warning restore CA1031 { _logger.LogError( ex, "Error deserializing message with Id '{MessageId}' and body '{MessageBody}'.", messageContext.Message.MessageId, messageContext.Message.Body); _messagingMonitor.HandleError(ex, messageContext.Message); return(false, null, null); } }
/// <summary> /// Starts the receive buffer until it's cancelled by the stopping token. /// </summary> /// <param name="stoppingToken">A <see cref="CancellationToken"/> that will stop the buffer when signalled.</param> /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous operation to receive the messages.</returns> public async Task RunAsync(CancellationToken stoppingToken) { await Task.Yield(); ChannelWriter <IQueueMessageContext> writer = _channel.Writer; try { while (true) { stoppingToken.ThrowIfCancellationRequested(); using (_monitor.MeasureThrottle()) { bool canWrite = await writer.WaitToWriteAsync(stoppingToken).ConfigureAwait(false); if (!canWrite) { break; } } IList <Message> messages; using (_monitor.MeasureReceive(_sqsQueueReader.QueueName, _sqsQueueReader.RegionSystemName)) { messages = await GetMessagesAsync(_prefetch, stoppingToken).ConfigureAwait(false); if (messages == null) { continue; } } if (_logger.IsEnabled(LogLevel.Trace)) { _logger.LogTrace("Downloaded {MessageCount} messages from queue {QueueName}.", messages.Count, _sqsQueueReader.QueueName); } foreach (Message message in messages) { IQueueMessageContext messageContext = _sqsQueueReader.ToMessageContext(message); await writer.WriteAsync(messageContext, stoppingToken).ConfigureAwait(false); } } } finally { _logger.LogInformation("Receive buffer for queue {QueueName} has completed, shutting down channel", _sqsQueueReader.Uri); writer.Complete(); } }
/// <summary> /// Starts the receive buffer until it's cancelled by the stopping token. /// </summary> /// <param name="stoppingToken">A <see cref="CancellationToken"/> that will stop the buffer when signalled.</param> /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous operation to receive the messages.</returns> public async Task RunAsync(CancellationToken stoppingToken) { await Task.Yield(); ChannelWriter <IQueueMessageContext> writer = _channel.Writer; try { while (true) { stoppingToken.ThrowIfCancellationRequested(); using (_monitor.MeasureThrottle()) { bool canWrite = await writer.WaitToWriteAsync(stoppingToken).ConfigureAwait(false); if (!canWrite) { break; } } IList <Message> messages; using (_monitor.MeasureReceive(_sqsQueueReader.QueueName, _sqsQueueReader.RegionSystemName)) { messages = await GetMessagesAsync(_prefetch, stoppingToken).ConfigureAwait(false); if (messages == null) { continue; } } foreach (Message message in messages) { IQueueMessageContext messageContext = _sqsQueueReader.ToMessageContext(message); // Complete all messages in the batch, rather than observing the CancellationToken to stop await writer.WriteAsync(messageContext, CancellationToken.None).ConfigureAwait(false); } } } finally { _logger.LogInformation("Receive buffer for queue {QueueName} has completed, shutting down channel", _sqsQueueReader.Uri); writer.Complete(); } }
public async Task DispatchMessageAsync( IQueueMessageContext messageContext, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return; } (bool success, Message typedMessage, MessageAttributes attributes) = await DeserializeMessage(messageContext, cancellationToken).ConfigureAwait(false); if (!success) { return; } var messageType = typedMessage.GetType(); var middleware = _middlewareMap.Get(messageContext.QueueName, messageType); if (middleware == null) { _logger.LogError( "Failed to dispatch. Middleware for message of type '{MessageTypeName}' not found in middleware map.", typedMessage.GetType().FullName); return; } var handleContext = new HandleMessageContext( messageContext.QueueName, messageContext.Message, typedMessage, messageType, messageContext, messageContext, messageContext.QueueUri, attributes); await middleware.RunAsync(handleContext, null, cancellationToken) .ConfigureAwait(false); }
public async Task DispatchMessageAsync( IQueueMessageContext messageContext, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return; } (bool success, Message typedMessage, MessageAttributes attributes) = await DeserializeMessage(messageContext, cancellationToken).ConfigureAwait(false); if (!success) { return; } var handlingSucceeded = false; Exception lastException = null; try { if (typedMessage != null) { _messageContextAccessor.MessageContext = new MessageContext(messageContext.Message, messageContext.QueueUri, attributes); handlingSucceeded = await CallMessageHandler(messageContext.QueueName, typedMessage) .ConfigureAwait(false); } if (handlingSucceeded) { await messageContext.DeleteMessageFromQueueAsync(cancellationToken).ConfigureAwait(false); } } #pragma warning disable CA1031 catch (Exception ex) #pragma warning restore CA1031 { _logger.LogError( ex, "Error handling message with Id '{MessageId}' and body '{MessageBody}'.", messageContext.Message.MessageId, messageContext.Message.Body); if (typedMessage != null) { _messagingMonitor.HandleException(typedMessage.GetType()); } _messagingMonitor.HandleError(ex, messageContext.Message); lastException = ex; } finally { try { if (!handlingSucceeded && _messageBackoffStrategy != null) { await UpdateMessageVisibilityTimeout(messageContext, typedMessage, lastException, cancellationToken).ConfigureAwait(false); } } finally { _messageContextAccessor.MessageContext = null; } } }
public Task DispatchMessageAsync(IQueueMessageContext messageContext, CancellationToken cancellationToken) { _spy?.Invoke(); DispatchedMessages.Add(messageContext); return(Task.CompletedTask); }