/// <summary> /// Publishes the specified message. /// </summary> /// <param name="message">The message.</param> public void Publish(Domain.Message message) { EnsureArg.IsNotNull(message, nameof(message)); if (message.CorrelationId.IsNullOrEmpty()) { message.CorrelationId = IdGenerator.Instance.Next; } var loggerState = new Dictionary <string, object> { [LogEventPropertyKeys.CorrelationId] = message.CorrelationId, }; using (this.logger.BeginScope(loggerState)) { if (message.Id.IsNullOrEmpty()) { message.Id = IdGenerator.Instance.Next; this.logger.LogDebug($"{{LogKey:l}} set message (id={message.Id})", LogKeys.Messaging); } if (message.Origin.IsNullOrEmpty()) { message.Origin = this.options.MessageScope; this.logger.LogDebug($"{{LogKey:l}} set message (origin={message.Origin})", LogKeys.Messaging); } // TODO: async publish! if (this.options.Mediator != null) { /*await */ this.options.Mediator.Publish(new MessagePublishedDomainEvent(message)).GetAwaiter().GetResult(); /*.AnyContext();*/ } var messageName = message.GetType().PrettyName(); // TODO: really need non-async Result? var serviceBusMessage = new Microsoft.Azure.ServiceBus.Message { Label = messageName, MessageId = message.Id, CorrelationId = message.CorrelationId.IsNullOrEmpty() ? IdGenerator.Instance.Next : message.CorrelationId, //Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), // TODO: use ISerializer here, compacter messages Body = this.serializer.SerializeToBytes(message), To = this.options.FilterScope }; serviceBusMessage.UserProperties.AddOrUpdate("Origin", this.options.MessageScope); this.logger.LogJournal(LogKeys.Messaging, $"publish (name={{MessageName}}, id={{MessageId}}, origin={{MessageOrigin}}, size={serviceBusMessage.Body.Length.Bytes().ToString("#.##")})", LogEventPropertyKeys.TrackPublishMessage, args: new[] { messageName, message.Id, message.Origin }); this.logger.LogTraceEvent(LogKeys.Messaging, message.Id, messageName, LogTraceEventNames.Message); this.options.Provider.CreateModel().SendAsync(serviceBusMessage).GetAwaiter().GetResult(); } }
/// <summary> /// Publishes the specified message. /// </summary> /// <param name="message">The message.</param> public void Publish(Domain.Message message) { EnsureArg.IsNotNull(message, nameof(message)); if (message.CorrelationId.IsNullOrEmpty()) { message.CorrelationId = IdGenerator.Instance.Next; } var messageName = message.GetType().PrettyName(); using (this.logger.BeginScope(new Dictionary <string, object> { [LogPropertyKeys.CorrelationId] = message.CorrelationId })) using (var scope = this.options.Tracer?.BuildSpan(messageName, LogKeys.AppMessaging, SpanKind.Producer).Activate(this.logger)) { if (message.Id.IsNullOrEmpty()) { message.Id = IdGenerator.Instance.Next; this.logger.LogDebug($"{{LogKey:l}} set message (id={message.Id})", LogKeys.AppMessaging); } if (message.Origin.IsNullOrEmpty()) { message.Origin = this.options.MessageScope; this.logger.LogDebug($"{{LogKey:l}} set message (origin={message.Origin})", LogKeys.AppMessaging); } // TODO: really need non-async Result? var serviceBusMessage = new Microsoft.Azure.ServiceBus.Message { Label = messageName, MessageId = message.Id, CorrelationId = message.CorrelationId.IsNullOrEmpty() ? IdGenerator.Instance.Next : message.CorrelationId, //Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), // TODO: use ISerializer here, compacter messages Body = this.serializer.SerializeToBytes(message), To = this.options.FilterScope }; if (this.options.Expiration.HasValue) { serviceBusMessage.TimeToLive = this.options.Expiration.Value; } serviceBusMessage.UserProperties.AddOrUpdate("Origin", message.Origin); if (scope?.Span != null) { // propagate the span infos serviceBusMessage.UserProperties.AddOrUpdate("TraceId", scope.Span.TraceId); serviceBusMessage.UserProperties.AddOrUpdate("SpanId", scope.Span.SpanId); } this.logger.LogJournal(LogKeys.AppMessaging, $"message publish: {messageName} (id={{MessageId}}, origin={{MessageOrigin}}, size={serviceBusMessage.Body.Length.Bytes().ToString("#.##")})", LogPropertyKeys.TrackPublishMessage, args: new[] { message.Id, message.Origin }); this.logger.LogTrace(LogKeys.AppMessaging, message.Id, messageName, LogTraceNames.Message); var policy = Policy.Handle <Exception>() .WaitAndRetry(this.options.Retries, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => { this.logger.LogWarning(ex, "{LogKey:l} could not publish message: {MessageId} after {Timeout}s ({ExceptionMessage})", LogKeys.AppMessaging, message.Id, $"{time.TotalSeconds:n1}", ex.Message); }); policy.Execute(() => { this.options.Provider.TopicClientFactory().SendAsync(serviceBusMessage).GetAwaiter().GetResult(); }); // TODO: async publish! if (this.options.Mediator != null) { /*await */ this.options.Mediator.Publish(new MessagePublishedDomainEvent(message)).GetAwaiter().GetResult(); /*.AnyContext();*/ } } }