Example #1
0
        public void WithHeaders_SerializationWorks()
        {
            // arrange
            var m = new MessageWithHeaders
            {
                Payload = _payload,
                Headers =
                {
                    { "key1", "value1"  },
                    { "key2", "value22" }
                }
            };

            // act
            var payload = _serializer.Serialize(typeof(MessageWithHeaders), m);
            var m2      = (MessageWithHeaders)_serializer.Deserialize(typeof(MessageWithHeaders), payload);

            // assert
            m2.Headers.Count.Should().Be(2);
            m2.Headers.ContainsKey("key1").Should().BeTrue();
            m2.Headers["key1"].ShouldBeEquivalentTo("value1");
            m2.Headers.ContainsKey("key2").Should().BeTrue();
            m2.Headers["key2"].ShouldBeEquivalentTo("value22");
            _payload.SequenceEqual(m2.Payload).Should().BeTrue();
        }
Example #2
0
        public void WhenRequestExpiredThenOnMessageExpiredIsCalled()
        {
            // arrange

            var onMessageExpiredMock = new Mock <Action <AbstractConsumerSettings, object> >();
            var consumerSettings     = new ConsumerSettings
            {
                Instances        = 1,
                Topic            = "topic1",
                ConsumerMode     = ConsumerMode.RequestResponse,
                ConsumerType     = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType      = typeof(SomeRequest),
                OnMessageExpired = onMessageExpiredMock.Object
            };

            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var request        = new SomeRequest();
            var requestMessage = new MessageWithHeaders();

            requestMessage.SetHeader(ReqRespMessageHeaders.Expires, _busMock.CurrentTime.AddSeconds(-10));

            _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage))
            .Returns(request);

            // act
            p.ProcessMessage(request).Wait();

            // assert
            _busMock.HandlerMock.Verify(x => x.OnHandle(It.IsAny <SomeRequest>(), It.IsAny <string>()), Times.Never); // the handler should not be called

            onMessageExpiredMock.Verify(x => x(consumerSettings, request), Times.Once);                               // callback called once
        }
        public void When_RequestExpired_Then_OnMessageExpiredIsCalled()
        {
            // arrange
            var onMessageExpiredMock = new Mock <Action <IMessageBus, AbstractConsumerSettings, object> >();
            var consumerSettings     = new HandlerBuilder <SomeRequest, SomeResponse>(new MessageBusSettings()).Topic(null).WithHandler <IRequestHandler <SomeRequest, SomeResponse> >().Instances(1).ConsumerSettings;

            consumerSettings.OnMessageExpired = onMessageExpiredMock.Object;

            var p = new ConsumerInstancePoolMessageProcessor <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var request        = new SomeRequest();
            var requestMessage = new MessageWithHeaders();

            requestMessage.SetHeader(ReqRespMessageHeaders.Expires, _busMock.CurrentTime.AddSeconds(-10));

            _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage))
            .Returns(request);

            // act
            p.ProcessMessage(request).Wait();

            // assert
            _busMock.HandlerMock.Verify(x => x.OnHandle(It.IsAny <SomeRequest>(), It.IsAny <string>()), Times.Never); // the handler should not be called

            onMessageExpiredMock.Verify(x => x(_busMock.Bus, consumerSettings, request), Times.Once);                 // callback called once
        }
Example #4
0
        public void WhenRequestMessageSerializedThenDeserializeGivesSameObject()
        {
            // arrange
            var r          = new RequestA();
            var rid        = "1";
            var replyTo    = "some_topic";
            var expires    = DateTimeOffset.UtcNow.AddMinutes(2);
            var reqMessage = new MessageWithHeaders();

            reqMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo);
            reqMessage.SetHeader(ReqRespMessageHeaders.RequestId, rid);
            reqMessage.SetHeader(ReqRespMessageHeaders.Expires, expires);

            // act
            var payload = Bus.SerializeRequest(typeof(RequestA), r, reqMessage, new Mock <ProducerSettings>().Object);

            Bus.DeserializeRequest(typeof(RequestA), payload, out var resMessage);

            // assert
            resMessage.Headers[ReqRespMessageHeaders.RequestId].Should().Be(rid);
            resMessage.Headers[ReqRespMessageHeaders.ReplyTo].Should().Be(replyTo);
            resMessage.TryGetHeader(ReqRespMessageHeaders.Expires, out DateTimeOffset? resExpires);

            resExpires.HasValue.Should().BeTrue();
            resExpires.Value.ToFileTime().Should().Be(expires.ToFileTime());
        }
        public override Task ProduceResponse(object request, MessageWithHeaders requestMessage, object response, MessageWithHeaders responseMessage, ConsumerSettings consumerSettings)
        {
            var replyTo = requestMessage.Headers[ReqRespMessageHeaders.ReplyTo];
            var kind    = (PathKind)requestMessage.GetHeaderAsInt(RequestHeaderReplyToKind);

            var responseMessagePayload = SerializeResponse(consumerSettings.ResponseType, response, responseMessage);

            return(ProduceToTransport(consumerSettings.ResponseType, response, replyTo, responseMessagePayload, kind));
        }
Example #6
0
        public override byte[] SerializeResponse(Type responseType, object response, MessageWithHeaders responseMessage)
        {
            if (!ProviderSettings.EnableMessageSerialization)
            {
                // the serialized payload is not going to be used
                return(null);
            }

            return(base.SerializeResponse(responseType, response, responseMessage));
        }
Example #7
0
        public override byte[] SerializeRequest(Type requestType, object request, MessageWithHeaders requestMessage, ProducerSettings producerSettings)
        {
            if (!ProviderSettings.EnableMessageSerialization)
            {
                // the serialized payload is not going to be used
                return(null);
            }

            return(base.SerializeRequest(requestType, request, requestMessage, producerSettings));
        }
Example #8
0
        public override Task ProduceRequest(object request, MessageWithHeaders requestMessage, string name, ProducerSettings producerSettings)
        {
            if (requestMessage is null)
            {
                throw new ArgumentNullException(nameof(requestMessage));
            }

            requestMessage.SetHeader(RequestHeaderReplyToKind, (int)Settings.RequestResponse.GetKind());
            return(base.ProduceRequest(request, requestMessage, name, producerSettings));
        }
Example #9
0
        public void WithoutHeaders_SerializationWorks()
        {
            // arrange
            var m = new MessageWithHeaders
            {
                Payload = _payload
            };

            // act
            var payload = _serializer.Serialize(typeof(MessageWithHeaders), m);
            var m2      = (MessageWithHeaders)_serializer.Deserialize(typeof(MessageWithHeaders), payload);

            // assert
            m2.Headers.Count.Should().Be(0);
            _payload.SequenceEqual(m2.Payload).Should().BeTrue();
        }
Example #10
0
        public void WithoutPayload_SerializationWorks()
        {
            // arrange
            var m = new MessageWithHeaders
            {
                Payload = null
            };

            // act
            var payload = _serializer.Serialize(typeof(MessageWithHeaders), m);
            var m2      = (MessageWithHeaders)_serializer.Deserialize(typeof(MessageWithHeaders), payload);

            // assert
            m2.Headers.Count.Should().Be(0);
            m2.Payload.Should().BeNull();
        }
Example #11
0
        public override Task ProduceResponse(object request, MessageWithHeaders requestMessage, object response, MessageWithHeaders responseMessage, ConsumerSettings consumerSettings)
        {
            if (requestMessage is null)
            {
                throw new ArgumentNullException(nameof(requestMessage));
            }
            if (consumerSettings is null)
            {
                throw new ArgumentNullException(nameof(consumerSettings));
            }

            var replyTo = requestMessage.Headers[ReqRespMessageHeaders.ReplyTo];
            var kind    = (PathKind)requestMessage.GetHeaderAsInt(RequestHeaderReplyToKind);

            var responseMessagePayload = SerializeResponse(consumerSettings.ResponseType, response, responseMessage);

            return(ProduceToTransport(consumerSettings.ResponseType, response, replyTo, responseMessagePayload, kind));
        }
        public virtual byte[] SerializeRequest(Type requestType, object request, string requestId, string replyTo, DateTimeOffset?expires)
        {
            var requestPayload = serializer.Serialize(requestType, request);

            // create the request wrapper message
            var requestMessage = new MessageWithHeaders(requestPayload);

            requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo);
            if (expires.HasValue)
            {
                requestMessage.SetHeader(ReqRespMessageHeaders.Expires, expires.Value);
            }

            var requestMessagePayload = messageWithHeadersSerializer.Serialize(typeof(MessageWithHeaders), requestMessage);

            return(requestMessagePayload);
        }
Example #13
0
        public void WhenRequestFailsThenOnMessageFaultIsCalledAndErrorResponseIsSent()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <AbstractConsumerSettings, object, Exception> >();
            var consumerSettings   = new ConsumerSettings
            {
                Instances      = 1,
                Topic          = "topic1",
                ConsumerMode   = ConsumerMode.RequestResponse,
                ConsumerType   = typeof(IRequestHandler <SomeRequest, SomeResponse>),
                MessageType    = typeof(SomeRequest),
                OnMessageFault = onMessageFaultMock.Object
            };

            var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var request        = new SomeRequest();
            var requestMessage = new MessageWithHeaders();
            var replyTo        = "reply-topic";
            var requestId      = "request-id";

            requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo);
            _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage))
            .Returns(request);

            var ex = new Exception("Something went bad");

            _busMock.HandlerMock.Setup(x => x.OnHandle(request, consumerSettings.Topic))
            .Returns(Task.FromException <SomeResponse>(ex));

            // act
            p.ProcessMessage(request).Wait();

            // assert
            _busMock.HandlerMock.Verify(x => x.OnHandle(request, consumerSettings.Topic),
                                        Times.Once); // handler called once

            onMessageFaultMock.Verify(
                x => x(consumerSettings, request, ex), Times.Once); // callback called once
            _busMock.BusMock.Verify(
                x => x.ProduceResponse(request, requestMessage, It.IsAny <SomeResponse>(), It.Is <MessageWithHeaders>(m => m.Headers[ReqRespMessageHeaders.RequestId] == requestId), It.IsAny <ConsumerSettings>()));
        }
Example #14
0
        public override Task ProduceToTransport(Type messageType, object message, string name, byte[] payload)
        {
            var req = DeserializeRequest(messageType, payload, out var requestMessage);

            var resp = OnReply(messageType, name, req);

            if (resp == null)
            {
                return(Task.CompletedTask);
            }

            var respMessage = new MessageWithHeaders();

            respMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestMessage.Headers[ReqRespMessageHeaders.RequestId]);
            var replyTo = requestMessage.Headers[ReqRespMessageHeaders.ReplyTo];

            var respPayload = SerializeResponse(resp.GetType(), resp, respMessage);

            return(OnResponseArrived(respPayload, replyTo));
        }
Example #15
0
        public void WithLargeHeader_SerializationWorks()
        {
            // arrange
            var largeValue = "System.InvalidOperationException: Image with id '_DSC0862.jpg' does not exist\r\n   at Sample.Images.Worker.Handlers.GenerateThumbnailRequestHandler.<OnHandle>d__3.MoveNext() in E:\\dev\\mygithub\\SlimMessageBus\\Samples\\Sample.Images.Worker\\Handlers\\GenerateThumbnailRequestHandler.cs:line 31\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n   at SlimMessageBus.Host.Kafka.TopicConsumerInstances.<ProcessMessage>d__13.MoveNext() in E:\\dev\\mygithub\\SlimMessageBus\\SlimMessageBus.Host.Kafka\\TopicSubscriberInstances.cs:line 109";
            var m          = new MessageWithHeaders
            {
                Payload = _payload,
                Headers =
                {
                    { "key1", largeValue }
                }
            };

            // act
            var payload = _serializer.Serialize(typeof(MessageWithHeaders), m);
            var m2      = (MessageWithHeaders)_serializer.Deserialize(typeof(MessageWithHeaders), payload);

            // assert
            m2.Headers.Count.Should().Be(1);
            m2.Headers.ContainsKey("key1").Should().BeTrue();
            m2.Headers["key1"].ShouldBeEquivalentTo(largeValue);
        }
Example #16
0
        public async Task When_RequestFails_Then_OnMessageFaultIsCalledAndErrorResponseIsSent()
        {
            // arrange
            var onMessageFaultMock = new Mock <Action <IMessageBus, AbstractConsumerSettings, object, Exception, object> >();
            var consumerSettings   = new HandlerBuilder <SomeRequest, SomeResponse>(new MessageBusSettings()).Topic(null).WithHandler <IRequestHandler <SomeRequest, SomeResponse> >().Instances(1).ConsumerSettings;

            consumerSettings.OnMessageFault = onMessageFaultMock.Object;

            var p = new ConsumerInstancePoolMessageProcessor <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>());

            var request        = new SomeRequest();
            var requestMessage = new MessageWithHeaders();
            var replyTo        = "reply-topic";
            var requestId      = "request-id";

            requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
            requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo);
            _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage)).Returns(request);

            var ex = new Exception("Something went bad");

            _busMock.HandlerMock.Setup(x => x.OnHandle(request, consumerSettings.Topic)).Returns(Task.FromException <SomeResponse>(ex));

            // act
            var exception = await p.ProcessMessage(request);

            // assert
            _busMock.HandlerMock.Verify(x => x.OnHandle(request, consumerSettings.Topic), Times.Once); // handler called once

            onMessageFaultMock.Verify(
                x => x(_busMock.Bus, consumerSettings, request, ex, It.IsAny <object>()), Times.Once); // callback called once

            _busMock.BusMock.Verify(
                x => x.ProduceResponse(request, requestMessage, It.IsAny <SomeResponse>(), It.Is <MessageWithHeaders>(m => m.Headers[ReqRespMessageHeaders.RequestId] == requestId), It.IsAny <ConsumerSettings>()));

            exception.Should().BeSameAs(ex);
        }
        public override async Task ProduceToTransport([NotNull] Type messageType, object message, string name, [NotNull] byte[] messagePayload, MessageWithHeaders messageWithHeaders = null)
        {
            AssertActive();

            // calculate message key
            var key          = GetMessageKey(messageType, message, name);
            var kafkaMessage = new Message {
                Key = key, Value = messagePayload
            };

            // calculate partition
            var partition = GetMessagePartition(messageType, message, name);

            _logger.LogTrace("Producing message {message} of type {messageType}, on topic {topic}, partition {partition}, key size {keySize}, payload size {messageSize}",
                             message, messageType.Name, name, partition, key?.Length ?? 0, messagePayload.Length);

            // send the message to topic
            var task = partition == NoPartition
                ? _producer.ProduceAsync(name, kafkaMessage)
                : _producer.ProduceAsync(new TopicPartition(name, new Partition(partition)), kafkaMessage);

            // ToDo: Introduce support for not awaited produce

            var deliveryResult = await task.ConfigureAwait(false);

            if (deliveryResult.Status == PersistenceStatus.NotPersisted)
            {
                throw new PublishMessageBusException($"Error while publish message {message} of type {messageType.Name} to topic {name}. Kafka persistence status: {deliveryResult.Status}");
            }

            // log some debug information
            _logger.LogDebug("Message {message} of type {messageType} delivered to topic-partition-offset {topicPartitionOffset}",
                             message, messageType.Name, deliveryResult.TopicPartitionOffset);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="messageType"></param>
        /// <param name="payload"></param>
        /// <param name="message"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public override async Task ProduceToTransport(Type messageType, object message, string name, byte[] payload, MessageWithHeaders messageWithHeaders = null)
        {
            AssertActive();

            _logger.LogDebug("Producing message {0} of type {1} on topic {2} with size {3}", message, messageType.Name, name, payload.Length);
            var producer = _producerByTopic.GetOrAdd(name);

            var ev = new EventData(payload);
            // ToDo: Add support for partition keys
            await producer.SendAsync(ev).ConfigureAwait(false);

            _logger.LogDebug("Delivered message {0} of type {1} on topic {2}", message, messageType.Name, name);
        }
        public override async Task ProduceToTransport(Type messageType, object message, string name, byte[] payload, MessageWithHeaders messageWithHeaders = null)
        {
            var result = await Database.PublishAsync(name, payload).ConfigureAwait(false);

            _logger.LogDebug("Produced message {0} of type {1} to redis channel {2} with result {3}", message, messageType, name, result);
        }
Example #20
0
        public override Task ProduceToTransport(Type messageType, object message, string name, byte[] payload, MessageWithHeaders messageWithHeaders = null)
        {
            // determine the SMB topic name if its a Azure SB queue or topic
            if (!_kindByTopic.TryGetValue(name, out var kind))
            {
                if (!_kindByMessageType.TryGetValue(messageType, out kind))
                {
                    // by default this will be a topic
                    kind = PathKind.Topic;
                }
            }

            return(ProduceToTransport(messageType, message, name, payload, kind));
        }
Example #21
0
        public override Task ProduceToTransport(Type messageType, object message, string name, byte[] messagePayload, MessageWithHeaders messageWithHeaders = null)
        {
            if (!_consumersByTopic.TryGetValue(name, out var consumers))
            {
                Log.DebugFormat(CultureInfo.InvariantCulture, "No consumers interested in message type {0} on topic {1}", messageType, name);
                return(Task.CompletedTask);
            }

            var tasks = new LinkedList <Task>();

            foreach (var consumer in consumers)
            {
                // obtain the consumer from DI
                Log.DebugFormat(CultureInfo.InvariantCulture, "Resolving consumer type {0}", consumer.ConsumerType);
                var consumerInstance = Settings.DependencyResolver.Resolve(consumer.ConsumerType);
                if (consumerInstance == null)
                {
                    Log.WarnFormat(CultureInfo.InvariantCulture, "The dependency resolver did not yield any instance of {0}", consumer.ConsumerType);
                    continue;
                }

                var messageForConsumer = !ProviderSettings.EnableMessageSerialization
                    ? message                                                        // prevent deep copy of the message
                    : consumer.ConsumerMode == ConsumerMode.RequestResponse
                        ? DeserializeRequest(messageType, messagePayload, out var _) // will pass a deep copy of the message
                        : DeserializeMessage(messageType, messagePayload);           // will pass a deep copy of the message

                Log.DebugFormat(CultureInfo.InvariantCulture, "Invoking {0} {1}", consumer.ConsumerMode == ConsumerMode.Consumer ? "consumer" : "handler", consumerInstance.GetType());
                var task = consumer.ConsumerMethod(consumerInstance, messageForConsumer, consumer.Topic);

                if (consumer.ConsumerMode == ConsumerMode.RequestResponse)
                {
                    var requestId = messageWithHeaders.Headers[ReqRespMessageHeaders.RequestId];

                    task = task.ContinueWith(x =>
                    {
                        if (x.IsFaulted || x.IsCanceled)
                        {
                            return(OnResponseArrived(null, name, requestId, x.IsCanceled ? "Cancelled" : x.Exception.Message, null));
                        }

                        var response        = consumer.ConsumerMethodResult(x);
                        var responsePayload = SerializeMessage(consumer.ResponseType, response);

                        return(OnResponseArrived(responsePayload, name, requestId, null, response));
                    }, TaskScheduler.Current).Unwrap();
                }

                tasks.AddLast(task);
            }

            Log.DebugFormat(CultureInfo.InvariantCulture, "Waiting on {0} consumer tasks", tasks.Count);
            return(Task.WhenAll(tasks));
        }
 public override Task ProduceRequest(object request, MessageWithHeaders requestMessage, string name, ProducerSettings producerSettings)
 {
     requestMessage.SetHeader(RequestHeaderReplyToKind, (int)Settings.RequestResponse.GetKind());
     return(base.ProduceRequest(request, requestMessage, name, producerSettings));
 }
Example #23
0
        public override Task ProduceToTransport(Type messageType, object message, string name, byte[] messagePayload, MessageWithHeaders messageWithHeaders = null)
        {
            if (!_consumersByTopic.TryGetValue(name, out var consumers))
            {
                _logger.LogDebug("No consumers interested in message type {messageType} on topic {topic}", messageType, name);
                return(Task.CompletedTask);
            }

            var tasks = new LinkedList <Task>();

            foreach (var consumer in consumers)
            {
                var task = OnMessageProduced(messageType, message, name, messagePayload, messageWithHeaders, consumer);
                if (task != null)
                {
                    tasks.AddLast(task);
                }
            }

            _logger.LogDebug("Waiting on {0} consumer tasks", tasks.Count);
            return(Task.WhenAll(tasks));
        }
Example #24
0
        private async Task OnMessageProduced(Type messageType, object message, string name, byte[] messagePayload, MessageWithHeaders messageWithHeaders, ConsumerSettings consumer)
        {
            // ToDo: Extension: In case of IMessageBus.Publish do not wait for the consumer method see https://github.com/zarusz/SlimMessageBus/issues/37

            string responseError = null;
            Task   consumerTask  = null;

            try
            {
                consumerTask = await ExecuteConsumer(messageType, message, messagePayload, consumer).ConfigureAwait(false);
            }
#pragma warning disable CA1031 // Intended, a catch all situation
            catch (Exception e)
#pragma warning restore CA1031
            {
                responseError = e.Message;
            }

            if (consumer.ConsumerMode == ConsumerMode.RequestResponse)
            {
                var requestId = messageWithHeaders.Headers[ReqRespMessageHeaders.RequestId];

                if (responseError != null)
                {
                    await OnResponseArrived(null, name, requestId, responseError, null).ConfigureAwait(false);
                }
                else
                {
                    var response        = consumer.ConsumerMethodResult(consumerTask);
                    var responsePayload = SerializeMessage(consumer.ResponseType, response);

                    await OnResponseArrived(responsePayload, name, requestId, null, response).ConfigureAwait(false);
                }
            }
        }
Example #25
0
        public override async Task ProduceToTransport(Type messageType, object message, string name, byte[] payload, MessageWithHeaders messageWithHeaders = null)
        {
            AssertActive();

            // calculate message key
            var key = GetMessageKey(messageType, message, name);

            // calculate partition
            var partition = GetMessagePartition(messageType, message, name);

            _logger.LogTrace("Producing message {0} of type {1}, on topic {2}, partition {3}, key length {4}, payload size {5}",
                             message, messageType.Name, name, partition, key?.Length ?? 0, payload.Length);

            // send the message to topic
            var task = partition == NoPartition
                ? _producer.ProduceAsync(name, key, payload)
                : _producer.ProduceAsync(name, key, 0, key?.Length ?? 0, payload, 0, payload.Length, partition);

            var deliveryReport = await task.ConfigureAwait(false);

            if (deliveryReport.Error.HasError)
            {
                throw new PublishMessageBusException($"Error while publish message {message} of type {messageType.Name} to topic {name}. Kafka response code: {deliveryReport.Error.Code}, reason: {deliveryReport.Error.Reason}");
            }

            // log some debug information
            _logger.LogDebug("Message {0} of type {1} delivered to topic-partition-offset {2}", message, messageType.Name, deliveryReport.TopicPartitionOffset);
        }