Exemplo n.º 1
0
 public async Task SubscribeToDeadLetterAsync(Func <PunchyMessage, Task> onMessageAsync, string groupId, CancellationToken cancellationToken, params string[] topics)
 {
     topics = topics.Select(topic => TopicNameHelpers.BuildDeadLetterTopicName(topic, groupId)).ToArray();
     await SubscribeAsync(onMessageAsync, groupId, cancellationToken, topics);
 }
        public async Task OnMessageAsync(IMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var badMessageNextLevel = TopicNameHelpers.ExtractBadMessageNextLevel(message.Topic);

            string badMessageNextLevelTopicName;

            if (badMessageNextLevel == badMessageMaxLevels)
            {
                badMessageNextLevelTopicName = TopicNameHelpers.BuildDeadLetterTopicName(message.Topic, groupId);
            }
            else
            {
                badMessageNextLevelTopicName = TopicNameHelpers.BuildBadMessageTopicName(message.Topic, badMessageNextLevel, groupId);
            }

            var attempts            = new List <Attempt>();
            var badMessageCandidate = message;

            message = GetSourceMessage(badMessageCandidate, attempts);

            // If message is null, retry time not ellapsed so will ignore this message for now.
            // It will be read again latter

            if (message != null)
            {
                try
                {
                    await onMessageAsync.Invoke(new PunchyMessage()
                    {
                        MessageAddress = message.MessageAddress,
                        MessageBytes   = message.MessageBytes,
                        Timestamp      = message.Timestamp,
                        Topic          = message.Topic,
                        Attempts       = attempts
                    });
                }
                catch (Exception exception)
                {
                    if (badMessageNextLevel < badMessageMaxLevels)
                    {
                        logger.LogWarning(exception, "Action failed for message, moving to bad message level '{BadMessageNextLevel}'. " +
                                          "Will try again in {RetrySeconds}. Topic: {Topic}; Original message address: {@MessageAddress}",
                                          badMessageNextLevel, configuration.LevelDelaysInSeconds[badMessageNextLevel],
                                          message.Topic, message.MessageAddress);
                    }
                    else // is final level
                    {
                        logger.LogError(exception, "Action failed for message, will NOT try again. Topic: {Topic}; Original message address: {@MessageAddress}",
                                        message.Topic, message.MessageAddress);
                    }

                    var badMessageContents = new BadMessageContents()
                    {
                        Exception            = exception,
                        SourceMessageAddress = badMessageCandidate.MessageAddress
                    };

                    await pubSub.PublishAsync(badMessageNextLevelTopicName,
                                              Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(badMessageContents)));
                }

                await badMessageCandidate.CommitAsync();
            }
        }