示例#1
0
 public long PublishAsync(string channel, string value)
 {
     if (pubSub.PublishAsync(channel, value) == 0)
     {
         //订阅者为0,或者订阅者出现异常,我们可以重试
         RepeatAction(channel, () =>
         {
             return(pubSub.PublishAsync(channel, value) > 0);
         });
     }
     return(0);
 }
示例#2
0
        private Task InvalidateAsync(params string[] keys)
        {
            if (options.WaitForAcknowledgment)
            {
                return(pubSub.PublishAsync(CreateMessage(keys)));
            }
            else
            {
                pubSub.PublishAsync(CreateMessage(keys));

                return(Task.CompletedTask);
            }
        }
        public async Task Should_be_able_to_publish_struct()
        {
            var message     = DateTime.UtcNow;
            var messageType = typeof(DateTime);
            await pubSub.PublishAsync(message, messageType, configure);

#pragma warning disable 4014
            pubSub.Received()
            .PublishAsync(
                Arg.Is(message),
                Arg.Is(configure),
                Arg.Any <CancellationToken>()
                );
#pragma warning restore 4014
        }
示例#4
0
        /// <summary>
        /// Publishes a message with a topic.
        /// When used with publisher confirms the task completes when the publish is confirmed.
        /// Task will throw an exception if the confirm is NACK'd or times out.
        /// </summary>
        /// <typeparam name="T">The message type</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// /// <param name="message">The message to publish</param>
        /// <param name="topic">The topic string</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns></returns>
        public static Task PublishAsync <T>(this IPubSub pubSub, T message, string topic, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");
            Preconditions.CheckNotNull(topic, "topic");

            return(pubSub.PublishAsync(message, c => c.WithTopic(topic), cancellationToken));
        }
示例#5
0
        /// <summary>
        /// Publishes a message.
        /// </summary>
        /// <typeparam name="T">The message type</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="configure">
        /// Fluent configuration e.g. x => x.WithTopic("*.brighton").WithPriority(2)
        /// </param>
        /// <param name="cancellationToken">The cancellation token</param>
        public static void Publish <T>(this IPubSub pubSub, T message, Action <IPublishConfiguration> configure, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            pubSub.PublishAsync(message, configure, cancellationToken)
            .GetAwaiter()
            .GetResult();
        }
示例#6
0
        public async Task Should_not_send_invalidation_message_when_not_enabled()
        {
            options.Enable = false;

            await sut.RemoveAsync("Key");

            A.CallTo(() => pubSub.PublishAsync(A <object> ._))
            .MustNotHaveHappened();
        }
示例#7
0
 public static async Task PublishBatchAsync <T>(
     this IPubSub pubSub,
     IEnumerable <T> messages,
     Action <IPublishConfiguration> configuration,
     CancellationToken cancellationToken = default
     )
 {
     foreach (var message in messages)
     {
         await pubSub.PublishAsync(message, configuration, cancellationToken).ConfigureAwait(false);
     }
 }
示例#8
0
        public static async Task PublishBatchInParallelAsync <T>(
            this IPubSub pubSub, IEnumerable <T> messages, CancellationToken cancellationToken = default
            )
        {
            var publishTasks = new List <Task>();

            foreach (var message in messages)
            {
                publishTasks.Add(pubSub.PublishAsync(message, cancellationToken));
            }

            await Task.WhenAll(publishTasks).ConfigureAwait(false);
        }
        /// <summary>
        /// Publishes a message with a topic.
        /// When used with publisher confirms the task completes when the publish is confirmed.
        /// Task will throw an exception if the confirm is NACK'd or times out.
        /// </summary>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="message">The message to publish</param>
        /// <param name="messageType">The message type</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns></returns>
        public static Task PublishAsync(this IPubSub pubSub, object message, Type messageType, CancellationToken cancellationToken = default)
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            return(pubSub.PublishAsync(message, messageType, c => { }, cancellationToken));
        }
        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();
            }
        }