Beispiel #1
0
        public Task <KafkaMessage <TKey, TValue>?> ConsumeAsync(CancellationToken cancellationToken)
        {
            return(Task.Run(() =>
            {
                try
                {
                    if (_consumer is null)
                    {
                        return null;
                    }

                    var consumeResult = _consumer.Consume(cancellationToken);

                    if (consumeResult is null || consumeResult.IsPartitionEOF)
                    {
                        Logger.LogInformation(consumeResult is null ? "No message received from consumer." : $"End of partition reached. Topic: {consumeResult.Topic} Partition: {consumeResult.Partition} Offset: {consumeResult.Offset}");

                        return null;
                    }

                    var messageProperties = ParseMessageHeaders(consumeResult, out var contentType, out var messageType);

                    if (string.IsNullOrWhiteSpace(contentType))
                    {
                        contentType = ContentTypes.Json;
                    }

                    var keyType = TypeCache <TKey> .AssemblyQualifiedName;
                    if (string.IsNullOrWhiteSpace(keyType))
                    {
                        Throw.Exception("Cannot find key assembly type name for: " + typeof(TKey).Name);
                    }

                    if (string.IsNullOrWhiteSpace(messageType))
                    {
                        Throw.Exception("Cannot find message assembly type name for: " + typeof(TKey).Name);
                    }

                    var key = _deserializationProvider.From <TKey>(consumeResult.Message.Key, contentType, keyType);
                    var value = _deserializationProvider.From <TValue>(consumeResult.Message.Value, contentType, messageType);

                    _offsetTracker.AddOffset(consumeResult.Partition, consumeResult.Offset);

                    return new KafkaMessage <TKey, TValue>(_acknowledgementAction, consumeResult.Partition.Value, consumeResult.Offset.Value)
                    {
                        Id = key,
                        Properties = messageProperties,
                        Value = value
                    };
                }
                catch (OperationCanceledException)
                {
                    return null;
                }
            }));
        }
Beispiel #2
0
        public async Task <List <SqsMessage <T> > > ConsumeAsync(CancellationToken cancellationToken)
        {
            if (_currentConsumerOptions is null || _client is null)
            {
                Throw.Exception(MisconfiguredConsumerMessage);
            }

            var request = new ReceiveMessageRequest
            {
                QueueUrl              = _currentConsumerOptions.QueueUrl,
                MaxNumberOfMessages   = _currentConsumerOptions.MaxNumberOfMessages,
                WaitTimeSeconds       = _currentConsumerOptions.WaitTimeSeconds,
                AttributeNames        = _currentConsumerOptions.SQSMessageAttributes,
                MessageAttributeNames = _currentConsumerOptions.CustomMessageAttributes
            };

            if (_currentConsumerOptions.VisibilityTimeout.HasValue)
            {
                request.VisibilityTimeout = _currentConsumerOptions.VisibilityTimeout.Value;
            }

            var response = await _client.ReceiveMessageAsync(request, cancellationToken);

            if (response is null || response.HttpStatusCode != HttpStatusCode.OK || response.Messages is null || response.Messages.Count == 0)
            {
                return(_emptyList);
            }

            var result = new List <SqsMessage <T> >(response.Messages.Count);

            foreach (var message in response.Messages)
            {
                var properties = new Dictionary <string, string>(message.Attributes.Count + message.MessageAttributes.Count, StringComparer.Ordinal);

                foreach (var attribute in message.Attributes)
                {
                    properties[attribute.Key] = attribute.Value;
                }

                foreach (var msgAttribute in message.MessageAttributes)
                {
                    properties[msgAttribute.Key] = msgAttribute.Value.StringValue;
                }

                var contentType = ContentTypes.Json;

                if (message.MessageAttributes.TryGetValue(KnownProperties.ContentType, out var cta))
                {
                    contentType = cta.StringValue;
                }

                var messageType = default(string);
                if (message.MessageAttributes.TryGetValue(KnownProperties.ValueTypeName, out var vtn))
                {
                    messageType = vtn.StringValue;
                }

                if (_acknowledgementAction is null)
                {
                    Throw.Exception("Acknowledgement action cannot be null for SQS message");
                }

                try
                {
                    result.Add(new SqsMessage <T>(_acknowledgementAction)
                    {
                        Id            = message.MessageId,
                        Properties    = properties,
                        ReceiptHandle = message.ReceiptHandle,
                        QueueUrl      = _currentConsumerOptions.QueueUrl,
                        Value         = _deserializationProvider.From <T>(message.Body, contentType, messageType ?? string.Empty)
                    });
                }
                catch (Exception e)
                {
                    // Swallow deserialization exception to prevent blocking the pipeline and processing of subsequent messages.
                    _logger.LogError(e, $"Error deserializing message body. {e.Message}. {nameof(message.MessageId)}:{message.MessageId}. {nameof(message.MD5OfBody)}:{message.MD5OfBody}");
                }
            }

            return(result);
        }