Beispiel #1
0
        private async Task <(bool, OperateResult)> SendWithoutRetryAsync(PublishedMessage message)
        {
            var startTime = DateTimeOffset.UtcNow;
            var stopwatch = Stopwatch.StartNew();

            var tracingResult = TracingBefore(message.Name, message.Content);
            var operationId   = tracingResult.Item1;

            var sendValues = tracingResult.Item2 != null
                ? CommonHelper.AddTracingHeaderProperty(message.Content, tracingResult.Item2)
                : message.Content;

            var result = await PublishAsync(message.Name, sendValues);

            stopwatch.Stop();
            if (result.Succeeded)
            {
                await SetSuccessfulState(message);

                TracingAfter(operationId, message.Name, sendValues, startTime, stopwatch.Elapsed);

                return(false, OperateResult.Success);
            }
            else
            {
                TracingError(operationId, message, result, startTime, stopwatch.Elapsed);

                var needRetry = await SetFailedState(message, result.Exception);

                return(needRetry, OperateResult.Failed(result.Exception));
            }
        }
Beispiel #2
0
        public static bool TryToRoute(PublishedMessage sender, Subscription receiver, out MessageRoute route, out PublisherSubscriberMismatch mismatch)
        {
            route    = null;
            mismatch = null;

            var transportsMatch = (sender.Transports ?? new string[0]).Contains(receiver.Destination.Scheme);

            var contentType = SelectContentType(sender, receiver);

            if (transportsMatch && contentType.IsNotEmpty())
            {
                route = new MessageRoute(sender.DotNetType, receiver.Destination, contentType)
                {
                    Publisher = sender.ServiceName,
                    Receiver  = receiver.ServiceName
                };
                return(true);
            }

            mismatch = new PublisherSubscriberMismatch(sender, receiver)
            {
                IncompatibleTransports   = !transportsMatch,
                IncompatibleContentTypes = contentType == null
            };

            return(false);
        }
Beispiel #3
0
        private bool UpdateMessageForRetry(PublishedMessage message)
        {
            var retryBehavior = RetryBehavior.DefaultRetry;

            var retries = ++message.Retries;

            message.ExpiresAt = message.Added.AddSeconds(retryBehavior.RetryIn(retries));

            var retryCount = Math.Min(_options.FailedRetryCount, retryBehavior.RetryCount);

            if (retries >= retryCount)
            {
                if (retries == _options.FailedRetryCount)
                {
                    try
                    {
                        _options.FailedThresholdCallback?.Invoke(MessageType.Subscribe, message.Name, message.Content);

                        _logger.SenderAfterThreshold(message.Id, _options.FailedRetryCount);
                    }
                    catch (Exception ex)
                    {
                        _logger.ExecutedThresholdCallbackFailed(ex);
                    }
                }
                return(false);
            }

            _logger.SenderRetrying(message.Id, retries);

            return(true);
        }
Beispiel #4
0
        public void Publish <T>(T message, Action <IPublishContext <T> > contextCallback)
            where T : class
        {
            PublishedMessage <T> published = null;

            try
            {
                _bus.Publish(message, context =>
                {
                    published = new PublishedMessage <T>(context);

                    contextCallback(context);
                });
            }
            catch (Exception ex)
            {
                if (published != null)
                {
                    published.SetException(ex);
                }
                throw;
            }
            finally
            {
                if (published != null)
                {
                    _published.Add(published);
                    _scenario.AddPublished(published);
                }
            }
        }
Beispiel #5
0
        public void DataStream()
        {
            var msg = new PublishedMessage {
                DataBytes = new byte[] { 1 }
            };

            Assert.AreEqual(1, msg.DataStream.ReadByte());
        }
Beispiel #6
0
 public PublisherSubscriberMismatch(PublishedMessage publisher, Subscription subscription)
 {
     MessageType            = subscription.MessageType;
     Publisher              = publisher.ServiceName;
     Subscriber             = subscription.ServiceName;
     SubscriberTransport    = subscription.Destination.Scheme;
     PublishedContentTypes  = publisher.ContentTypes;
     SubscriberContentTypes = subscription.Accept;
 }
Beispiel #7
0
        private static string SelectContentType(PublishedMessage sender, Subscription receiver)
        {
            var matchingContentTypes = receiver.Accept.Intersect(sender.ContentTypes).ToArray();
            // Always try to use the versioned or specific reader/writer if one exists
            var contentType = matchingContentTypes.FirstOrDefault(x => x != "application/json")
                              ?? matchingContentTypes.FirstOrDefault();

            return(contentType);
        }
 public static async Task ChangeStateAsync(
     this IStateChanger @this, PublishedMessage message, IState state, IStorageConnection connection)
 {
     using (var transaction = connection.CreateTransaction())
     {
         @this.ChangeState(message, state, transaction);
         await transaction.CommitAsync();
     }
 }
Beispiel #9
0
 public void UpdateMessage(PublishedMessage message)
 {
     if (message == null)
     {
         throw new ArgumentNullException(nameof(message));
     }
     _dbContext.Set <PublishedMessage>().Update(message);
     _dbContext.SaveChanges();
 }
Beispiel #10
0
        protected override Task ExecuteAsync(PublishedMessage message, ITransaction transaction,
                                             CancellationToken cancel = default(CancellationToken))
        {
            var connection = (InMemoryStorageConnection)ServiceProvider.GetService <IStorageConnection>();

            connection.PublishedMessages.Add(message);

            return(Task.CompletedTask);
        }
Beispiel #11
0
        private async Task <bool> SetFailedState(PublishedMessage message, Exception ex)
        {
            AddErrorReasonToContent(message, ex);

            var needRetry = UpdateMessageForRetry(message);

            await _stateChanger.ChangeStateAsync(message, new FailedState(), _connection);

            return(needRetry);
        }
 public PublishedMessageEntity(PublishedMessage publishedMessage)
 {
     this.Id         = publishedMessage.Id;
     this.Name       = publishedMessage.Name;
     this.Content    = publishedMessage.Content;
     this.Retries    = publishedMessage.Retries;
     this.StatusName = publishedMessage.StatusName;
     this.Added      = publishedMessage.Added;
     this.ExpiresAt  = publishedMessage.ExpiresAt;
 }
 public void Add(PublishedMessage message)
 {
     lock (_messages)
     {
         if (_messages.Add(message))
         {
             _published.Set();
         }
     }
 }
Beispiel #14
0
        public void Publish <T>(string name, T contentObj, string callbackName = null)
        {
            var message = new PublishedMessage
            {
                Id         = SnowflakeId.Default().NextId(),
                Name       = name,
                Content    = Serialize(contentObj, callbackName),
                StatusName = StatusName.Scheduled
            };

            PublishAsyncInternal(message).GetAwaiter().GetResult();
        }
Beispiel #15
0
        public async Task PublishAsync <T>(string name, T contentObj, string callbackName = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var message = new PublishedMessage
            {
                Id         = SnowflakeId.Default().NextId(),
                Name       = name,
                Content    = Serialize(contentObj, callbackName),
                StatusName = StatusName.Scheduled
            };

            await PublishAsyncInternal(message);
        }
Beispiel #16
0
        public void ChangeState(PublishedMessage message, IState state, IStorageTransaction transaction)
        {
            var now = DateTime.Now;

            if (state.ExpiresAfter != null)
            {
                message.ExpiresAt = now.Add(state.ExpiresAfter.Value);
            }
            else
            {
                message.ExpiresAt = null;
            }

            message.StatusName = state.Name;
            state.Apply(message, transaction);
            transaction.UpdateMessage(message);
        }
Beispiel #17
0
        public void use_json_if_that_is_the_only_match()
        {
            var published = new PublishedMessage(typeof(Message1))
            {
                ContentTypes = new string[] { "application/json", "app/v2", "app/v3" },
                Transports   = new string[] { "loopback" }
            };

            var subscription = new Subscription(typeof(Message1), "loopback://one".ToUri());

            subscription.Accept = new string[] { "application/json", "app/v4", "app/v5" };

            MessageRoute.TryToRoute(published, subscription, out MessageRoute route, out PublisherSubscriberMismatch mismatch)
            .ShouldBeTrue();

            route.ContentType.ShouldBe("application/json");
        }
Beispiel #18
0
 public OperateResult PublishAsync(string keyName, PublishedMessage content)
 {
     try
     {
         return(_executor.PublishAsync(keyName, content.exchangeName, content.ToJson()).Result);
     }
     catch
     {
         try
         {
             return(_executor.PublishAsync(keyName, content.exchangeName, content.ToJson()).Result);
         }
         catch (Exception ex)
         {
             return(OperateResult.Failed(ex));
         }
     }
 }
Beispiel #19
0
        protected override async Task ExecuteAsync(PublishedMessage message, ITransaction transaction,
                                                   CancellationToken cancel = default(CancellationToken))
        {
            var dbContext = (DbContext)base.ServiceProvider.GetRequiredService(_options.DbContextType);

            if (NotUseTransaction)
            {
                dbContext.Entry(message).Property("Version").CurrentValue = _options.Version;
                dbContext.Set <PublishedMessage>().Add(message);
                await dbContext.SaveChangesAsync(cancel);

                return;
            }

            dbContext.Entry(message).Property("Version").CurrentValue = _options.Version;
            dbContext.Set <PublishedMessage>().Add(message);
            await dbContext.SaveChangesAsync(cancel);
        }
Beispiel #20
0
        private void TracingError(Guid operationId, PublishedMessage message, OperateResult result, DateTimeOffset startTime, TimeSpan du)
        {
            var ex = new PublisherSentFailedException(result.ToString(), result.Exception);

            _logger.MessagePublishException(message.Id, result.ToString(), ex);

            var eventData = new BrokerPublishErrorEventData(
                operationId,
                "",
                ServersAddress,
                message.Name,
                message.Content,
                ex,
                startTime,
                du);

            s_diagnosticListener.WritePublishError(eventData);
        }
 public static void WritePublishMessageStoreAfter(this DiagnosticListener @this,
                                                  Guid operationId,
                                                  PublishedMessage message,
                                                  [CallerMemberName] string operation = "")
 {
     if (@this.IsEnabled(AfterPublishMessageStore))
     {
         @this.Write(AfterPublishMessageStore, new
         {
             OperationId    = operationId,
             Operation      = operation,
             MessageId      = message.Id,
             MessageName    = message.Name,
             MessageContent = message.Content,
             Timestamp      = Stopwatch.GetTimestamp()
         });
     }
 }
Beispiel #22
0
        public void UpdateMessage(PublishedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var msg = _connection.PublishedMessages.FirstOrDefault(x => message.Id == x.Id);

            if (msg == null)
            {
                return;
            }
            msg.Retries    = message.Retries;
            msg.Content    = message.Content;
            msg.ExpiresAt  = message.ExpiresAt;
            msg.StatusName = message.StatusName;
        }
Beispiel #23
0
        public void mismatch_with_no_matching_content_types_and_transport()
        {
            var published = new PublishedMessage(typeof(Message1))
            {
                ContentTypes = new string[] { "one", "two" },
                Transports   = new string[] { "jasper" }
            };

            var subscription = new Subscription(typeof(Message1), "fake://one".ToUri());

            subscription.Accept = new string[] { "three" };

            MessageRoute.TryToRoute(published, subscription, out MessageRoute route, out PublisherSubscriberMismatch mismatch)
            .ShouldBeFalse();

            mismatch.IncompatibleContentTypes.ShouldBeTrue();
            mismatch.IncompatibleTransports.ShouldBeTrue();
        }
Beispiel #24
0
        public void mismatch_with_no_matching_content_types()
        {
            var published = new PublishedMessage(typeof(Message1))
            {
                ContentTypes = new string[] { "one", "two" }
            };

            var subscription = new Subscription(typeof(Message1), "loopback://one".ToUri());

            subscription.Accept = new string[] { "three" };

            MessageRoute.TryToRoute(published, subscription, out MessageRoute route, out PublisherSubscriberMismatch mismatch)
            .ShouldBeFalse();

            mismatch.IncompatibleContentTypes.ShouldBeTrue();
            mismatch.PublishedContentTypes.ShouldBe(published.ContentTypes);
            mismatch.SubscriberContentTypes.ShouldBe(subscription.Accept);
        }
Beispiel #25
0
        public void MessageID_Is_Unique()
        {
            var a = new PublishedMessage
            {
                Topics         = new[] { "topic" },
                Sender         = _self,
                SequenceNumber = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
                DataBytes      = new byte[] { 0, 1, 0xfe, 0xff }
            };
            var b = new PublishedMessage
            {
                Topics         = new[] { "topic" },
                Sender         = _other,
                SequenceNumber = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
                DataBytes      = new byte[] { 0, 1, 0xfe, 0xff }
            };

            Assert.AreNotEqual(a.MessageId, b.MessageId);
        }
Beispiel #26
0
        public async Task <OperateResult> SendAsync(PublishedMessage message)
        {
            return(await Task.Run(async() =>
            {
                bool retry;
                OperateResult result;
                do
                {
                    var executedResult = await SendWithoutRetryAsync(message);
                    result = executedResult.Item2;
                    if (result == OperateResult.Success)
                    {
                        return result;
                    }
                    retry = executedResult.Item1;
                } while (retry);

                return result;
            }));
        }
        //============================================================================
        //====================  Before publish store message      ====================
        //============================================================================
        public static Guid WritePublishMessageStoreBefore(this DiagnosticListener @this,
                                                          PublishedMessage message,
                                                          [CallerMemberName] string operation = "")
        {
            if (@this.IsEnabled(BeforePublishMessageStore))
            {
                var operationId = Guid.NewGuid();

                @this.Write(BeforePublishMessageStore, new
                {
                    OperationId    = operationId,
                    Operation      = operation,
                    MessageName    = message.Name,
                    MessageContent = message.Content
                });

                return(operationId);
            }

            return(Guid.Empty);
        }
Beispiel #28
0
        public PublishedMessage Send(object message)
        {
            string serializedMsg = null;

            if (Context.Serializer != null)
            {
                serializedMsg = Context.Serializer.Serialize(message);
            }

            int byteCount;

            SendIntl(serializedMsg, out byteCount);
            var publishedMessage = new PublishedMessage(message)
            {
                SerializedMessage = serializedMsg,
                SendTime          = DateTime.Now,
                ByteCount         = byteCount
            };

            return(publishedMessage);
        }
Beispiel #29
0
        private Result StoreMessage(MessageContext message, PublishedMessage receive)
        {
            var queueExector = _selector.GetTopicExector(message.Name);

            if (queueExector != null)
            {
                object        reflect    = Activator.CreateInstance(queueExector.ImplTypeInfo);
                var           methodInfo = queueExector.MethodInfo;
                var           parameters = methodInfo.GetParameters();
                List <object> objParams  = new List <object>();
                objParams = receive.msgBeanJson.ToModel(objParams);
                for (int i = 0; i < parameters.Length; i++)
                {
                    objParams[i] = objParams[i].ToJson().ToModel(parameters[i].ParameterType);
                }
                var result = methodInfo.Invoke(reflect, objParams.ToArray()) as Result;

                return(result);
            }
            return(Result.Fail(0));
        }
Beispiel #30
0
        private async Task <List <MessageRoute> > compileRoutes(Type messageType)
        {
            var list = new List <MessageRoute>();

            var modelWriter = _serializers.WriterFor(messageType);
            var supported   = modelWriter.ContentTypes;

            foreach (var channel in _channels.AllKnownChannels().Where(x => x.ShouldSendMessage(messageType)))
            {
                var contentType = supported.FirstOrDefault(x => x != "application/json") ?? "application/json";

                if (contentType.IsNotEmpty())
                {
                    list.Add(new MessageRoute(messageType, modelWriter, channel, contentType)
                    {
                    });
                }
            }

            var subscriptions = await _subscriptions.GetSubscribersFor(messageType);

            if (subscriptions.Any())
            {
                var published = new PublishedMessage(messageType, modelWriter, _channels);


                foreach (var subscription in subscriptions)
                {
                    if (MessageRoute.TryToRoute(published, subscription, out MessageRoute route,
                                                out PublisherSubscriberMismatch mismatch))
                    {
                        route.Writer  = modelWriter[route.ContentType];
                        route.Channel = _channels.GetOrBuildChannel(route.Destination);
                        list.Add(route);
                    }
                    else
                    {
                        _logger.SubscriptionMismatch(mismatch);
                    }
                }
		public void AddPublished(PublishedMessage message)
		{
			_published.Add(message);
		}