static async Task <bool> ScheduleSend(SendEndpointContext clientContext, AzureServiceBusSendContext <T> context) { var now = DateTime.UtcNow; var enqueueTimeUtc = context.ScheduledEnqueueTimeUtc.Value; if (enqueueTimeUtc < now) { LogContext.Debug?.Log("The scheduled time was in the past, sending: {ScheduledTime}", context.ScheduledEnqueueTimeUtc); return(false); } try { var brokeredMessage = CreateBrokeredMessage(context); var sequenceNumber = await clientContext.ScheduleSend(brokeredMessage, enqueueTimeUtc).ConfigureAwait(false); context.SetScheduledMessageId(sequenceNumber); context.LogScheduled(enqueueTimeUtc); return(true); } catch (ArgumentOutOfRangeException) { LogContext.Debug?.Log("The scheduled time was rejected by the server, sending: {MessageId}", context.MessageId); return(false); } }
static void AddTransportHeaders(StartedActivity?startedActivity, AzureServiceBusSendContext <T> context) { if (!startedActivity.HasValue) { return; } var activity = startedActivity.Value; activity.AddTag(nameof(context.PartitionKey), context.PartitionKey); activity.AddTag(nameof(context.SessionId), context.SessionId); }
bool IsCancelScheduledSend(AzureServiceBusSendContext <T> context, out long sequenceNumber) { if (_message is CancelScheduledMessage cancelScheduledMessage) { if (context.TryGetScheduledMessageId(out sequenceNumber) || context.TryGetSequenceNumber(cancelScheduledMessage.TokenId, out sequenceNumber)) { return(true); } } sequenceNumber = default; return(false); }
Message CreateBrokeredMessage <T>(AzureServiceBusSendContext <T> context) where T : class { var brokeredMessage = new Message(context.Body) { ContentType = context.ContentType.MediaType }; brokeredMessage.UserProperties.SetTextHeaders(context.Headers, (_, text) => text); if (context.TimeToLive.HasValue) { brokeredMessage.TimeToLive = context.TimeToLive.Value; } if (context.MessageId.HasValue) { brokeredMessage.MessageId = context.MessageId.Value.ToString("N"); } if (context.CorrelationId.HasValue) { brokeredMessage.CorrelationId = context.CorrelationId.Value.ToString("N"); } CopyIncomingIdentifiersIfPresent(context); if (context.PartitionKey != null) { brokeredMessage.PartitionKey = context.PartitionKey; } var sessionId = string.IsNullOrWhiteSpace(context.SessionId) ? context.ConversationId?.ToString("N") : context.SessionId; if (!string.IsNullOrWhiteSpace(sessionId)) { brokeredMessage.SessionId = sessionId; if (context.ReplyToSessionId == null) { brokeredMessage.ReplyToSessionId = sessionId; } } if (context.ReplyToSessionId != null) { brokeredMessage.ReplyToSessionId = context.ReplyToSessionId; } return(brokeredMessage); }
static BrokeredMessage CreateBrokeredMessage(AzureServiceBusSendContext <T> context) { var brokeredMessage = new BrokeredMessage(context.GetBodyStream()) { ContentType = context.ContentType.MediaType, ForcePersistence = context.Durable }; brokeredMessage.Properties.SetTextHeaders(context.Headers, (_, text) => text); if (context.TimeToLive.HasValue) { brokeredMessage.TimeToLive = context.TimeToLive.Value; } if (context.MessageId.HasValue) { brokeredMessage.MessageId = context.MessageId.Value.ToString("N"); } if (context.CorrelationId.HasValue) { brokeredMessage.CorrelationId = context.CorrelationId.Value.ToString("N"); } if (context.PartitionKey != null) { brokeredMessage.PartitionKey = context.PartitionKey; } var sessionId = string.IsNullOrWhiteSpace(context.SessionId) ? context.ConversationId?.ToString("N") : context.SessionId; if (!string.IsNullOrWhiteSpace(sessionId)) { brokeredMessage.SessionId = sessionId; if (context.ReplyToSessionId == null) { brokeredMessage.ReplyToSessionId = sessionId; } } if (context.ReplyToSessionId != null) { brokeredMessage.ReplyToSessionId = context.ReplyToSessionId; } return(brokeredMessage); }
static Message CreateBrokeredMessage(AzureServiceBusSendContext <T> context) { var brokeredMessage = new Message(context.Body) { ContentType = context.ContentType.MediaType }; brokeredMessage.UserProperties.Set(context.Headers); if (context.TimeToLive.HasValue) { brokeredMessage.TimeToLive = context.TimeToLive > TimeSpan.Zero ? context.TimeToLive.Value : TimeSpan.FromSeconds(1); } if (context.MessageId.HasValue) { brokeredMessage.MessageId = context.MessageId.Value.ToString("N"); } if (context.CorrelationId.HasValue) { brokeredMessage.CorrelationId = context.CorrelationId.Value.ToString("N"); } if (context.PartitionKey != null) { brokeredMessage.PartitionKey = context.PartitionKey; } if (!string.IsNullOrWhiteSpace(context.SessionId)) { brokeredMessage.SessionId = context.SessionId; if (context.ReplyToSessionId == null) { brokeredMessage.ReplyToSessionId = context.SessionId; } } if (context.ReplyToSessionId != null) { brokeredMessage.ReplyToSessionId = context.ReplyToSessionId; } return(brokeredMessage); }
public ConsumeContext Deserialize(ReceiveContext receiveContext) { var body = Encoding.UTF8.GetString(receiveContext.GetBody()); var customMessage = JsonConvert.DeserializeObject <CustomMessage>(body); var serviceBusSendContext = new AzureServiceBusSendContext <CustomMessage>(customMessage, CancellationToken.None); string[] messageTypes = { "urn:message:MassTransitSample:CustomMessage" }; var serviceBusContext = receiveContext as ServiceBusReceiveContext; serviceBusSendContext.ContentType = new ContentType(JsonMessageSerializer.JsonContentType.ToString()); serviceBusSendContext.SourceAddress = serviceBusContext.InputAddress; serviceBusSendContext.SessionId = serviceBusContext.SessionId; // sending JToken because we are using default Newtonsoft deserializer/serializer var messageEnv = new JsonMessageEnvelope(serviceBusSendContext, JObject.Parse(body), messageTypes); return(new JsonConsumeContext(JsonSerializer.CreateDefault(), receiveContext, messageEnv)); }
public async Task Send(SendEndpointContext clientContext) { var context = new AzureServiceBusSendContext <T>(_message, _cancellationToken); try { await _pipe.Send(context).ConfigureAwait(false); CopyIncomingIdentifiersIfPresent(context); if (IsCancelScheduledSend(context, out var sequenceNumber)) { await CancelScheduledSend(clientContext, sequenceNumber).ConfigureAwait(false); return; } if (context.ScheduledEnqueueTimeUtc.HasValue) { var scheduled = await ScheduleSend(clientContext, context).ConfigureAwait(false); if (scheduled) { return; } } await _observer.PreSend(context).ConfigureAwait(false); var brokeredMessage = CreateBrokeredMessage(context); await clientContext.Send(brokeredMessage).ConfigureAwait(false); context.LogSent(); await _observer.PostSend(context).ConfigureAwait(false); } catch (Exception ex) { await _observer.SendFault(context, ex).ConfigureAwait(false); throw; } }
public async Task Should_create_the_brokered_message_receiver() { var message = new Mock <Message>(); message.Object.ContentType = JsonMessageSerializer.ContentTypeHeaderValue; message.Object.MessageId = NewId.NextGuid().ToString(); using (var stream = new MemoryStream()) { ServiceBusSendContext <PingMessage> context = new AzureServiceBusSendContext <PingMessage>(new PingMessage(), CancellationToken.None); var envelope = new JsonMessageEnvelope(context, context.Message, TypeMetadataCache <PingMessage> .MessageTypeNames); using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) using (var jsonWriter = new JsonTextWriter(writer)) { jsonWriter.Formatting = Formatting.Indented; JsonMessageSerializer.Serializer.Serialize(jsonWriter, envelope, typeof(MessageEnvelope)); jsonWriter.Flush(); writer.Flush(); } message.Object.Body = stream.ToArray(); } var binder = new Mock <IBinder>(); LogContext.ConfigureCurrentLogContext(); var handler = Bus.Factory.CreateBrokeredMessageReceiver(binder.Object, LogContext.Current.Logger, cfg => { cfg.InputAddress = new Uri("sb://masstransit-build.servicebus.windows.net/input-queue"); cfg.UseRetry(x => x.Intervals(10, 100, 500, 1000)); cfg.Consumer(() => new Consumer()); }); Console.WriteLine(handler.GetProbeResult().ToJsonString()); // await handler.Handle(message.Object); }
public ConsumeContext Deserialize(ReceiveContext receiveContext) { var body = Encoding.UTF8.GetString(receiveContext.GetBody()); var customMessage = JsonConvert.DeserializeObject <EventGridEvent>(body); var serviceBusSendContext = new AzureServiceBusSendContext <EventGridEvent>(customMessage, CancellationToken.None); // this is the default scheme, that has to match in order messages to be processed // EventGrid messages type of EventGridEvent within namespace Microsoft.Azure.EventGrid.Models string[] messageTypes = { "urn:message:Microsoft.Azure.EventGrid.Models:EventGridEvent" }; var serviceBusContext = receiveContext as ServiceBusReceiveContext; serviceBusSendContext.ContentType = new ContentType(JsonMessageSerializer.JsonContentType.ToString()); serviceBusSendContext.SourceAddress = serviceBusContext.InputAddress; serviceBusSendContext.SessionId = serviceBusContext.SessionId; // sending JToken because we are using default Newtonsoft deserializer/serializer var messageEnv = new JsonMessageEnvelope(serviceBusSendContext, JObject.Parse(body), messageTypes); return(new JsonConsumeContext(JsonSerializer.CreateDefault(), receiveContext, messageEnv)); }
static void CopyIncomingIdentifiersIfPresent(AzureServiceBusSendContext <T> context) { if (context.TryGetPayload <ConsumeContext>(out var consumeContext) && consumeContext.TryGetPayload <BrokeredMessageContext>(out var brokeredMessageContext)) { if (context.SessionId == null) { if (brokeredMessageContext.ReplyToSessionId != null) { context.SessionId = brokeredMessageContext.ReplyToSessionId; } else if (brokeredMessageContext.SessionId != null) { context.SessionId = brokeredMessageContext.SessionId; } } if (context.PartitionKey == null && brokeredMessageContext.PartitionKey != null) { context.PartitionKey = brokeredMessageContext.PartitionKey; } } }
void CopyIncomingIdentifiersIfPresent <T>(AzureServiceBusSendContext <T> sendContext) where T : class { if (sendContext.TryGetPayload <ConsumeContext>(out var consumeContext)) { if (consumeContext.TryGetPayload <BrokeredMessageContext>(out var brokeredMessageContext)) { if (sendContext.SessionId == null && brokeredMessageContext.ReplyToSessionId != null) { sendContext.SessionId = brokeredMessageContext.ReplyToSessionId; } if (sendContext.SessionId == null && brokeredMessageContext.SessionId != null) { sendContext.SessionId = brokeredMessageContext.SessionId; } if (sendContext.PartitionKey == null && brokeredMessageContext.PartitionKey != null) { sendContext.PartitionKey = brokeredMessageContext.PartitionKey; } } } }
public async Task Send(SendEndpointContext clientContext) { LogContext.SetCurrentIfNull(_context.LogContext); var context = new AzureServiceBusSendContext <T>(_message, _cancellationToken); await _pipe.Send(context).ConfigureAwait(false); CopyIncomingIdentifiersIfPresent(context); StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context, (nameof(context.PartitionKey), context.PartitionKey), (nameof(context.SessionId), context.SessionId)); try { if (IsCancelScheduledSend(context, out var sequenceNumber)) { await CancelScheduledSend(clientContext, sequenceNumber).ConfigureAwait(false); return; } if (context.ScheduledEnqueueTimeUtc.HasValue) { var scheduled = await ScheduleSend(clientContext, context).ConfigureAwait(false); if (scheduled) { return; } } if (_context.SendObservers.Count > 0) { await _context.SendObservers.PreSend(context).ConfigureAwait(false); } var brokeredMessage = CreateBrokeredMessage(context); await clientContext.Send(brokeredMessage).ConfigureAwait(false); context.LogSent(); if (_context.SendObservers.Count > 0) { await _context.SendObservers.PostSend(context).ConfigureAwait(false); } } catch (Exception ex) { if (_context.SendObservers.Count > 0) { await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false); } throw; } finally { activity?.Stop(); } }
Task ISendTransport.Send <T>(T message, IPipe <SendContext <T> > pipe, CancellationToken cancellationToken) { IPipe <SendEndpointContext> clientPipe = Pipe.ExecuteAsync <SendEndpointContext>(async clientContext => { var context = new AzureServiceBusSendContext <T>(message, cancellationToken); try { await pipe.Send(context).ConfigureAwait(false); if (message is CancelScheduledMessage cancelScheduledMessage && (context.TryGetScheduledMessageId(out var sequenceNumber) || context.TryGetSequencyNumber(cancelScheduledMessage.TokenId, out sequenceNumber))) { try { await clientContext.CancelScheduledSend(sequenceNumber).ConfigureAwait(false); if (_log.IsDebugEnabled) { _log.DebugFormat("Canceled Scheduled: {0} {1}", sequenceNumber, clientContext.EntityPath); } } catch (MessageNotFoundException exception) { if (_log.IsDebugEnabled) { _log.DebugFormat("The scheduled message was not found: {0}", exception.Message); } } return; } await _observers.PreSend(context).ConfigureAwait(false); var brokeredMessage = new Message(context.Body) { ContentType = context.ContentType.MediaType }; brokeredMessage.UserProperties.SetTextHeaders(context.Headers, (_, text) => text); if (context.TimeToLive.HasValue) { brokeredMessage.TimeToLive = context.TimeToLive.Value; } if (context.MessageId.HasValue) { brokeredMessage.MessageId = context.MessageId.Value.ToString("N"); } if (context.CorrelationId.HasValue) { brokeredMessage.CorrelationId = context.CorrelationId.Value.ToString("N"); } CopyIncomingIdentifiersIfPresent(context); if (context.PartitionKey != null) { brokeredMessage.PartitionKey = context.PartitionKey; } var sessionId = string.IsNullOrWhiteSpace(context.SessionId) ? context.ConversationId?.ToString("N") : context.SessionId; if (!string.IsNullOrWhiteSpace(sessionId)) { brokeredMessage.SessionId = sessionId; if (context.ReplyToSessionId == null) { brokeredMessage.ReplyToSessionId = sessionId; } } if (context.ReplyToSessionId != null) { brokeredMessage.ReplyToSessionId = context.ReplyToSessionId; } if (context.ScheduledEnqueueTimeUtc.HasValue) { var enqueueTimeUtc = context.ScheduledEnqueueTimeUtc.Value; sequenceNumber = await clientContext.ScheduleSend(brokeredMessage, enqueueTimeUtc).ConfigureAwait(false); context.SetScheduledMessageId(sequenceNumber); context.LogScheduled(enqueueTimeUtc); } else { await clientContext.Send(brokeredMessage).ConfigureAwait(false); context.LogSent(); await _observers.PostSend(context).ConfigureAwait(false); } } catch (Exception ex) { await _observers.SendFault(context, ex).ConfigureAwait(false); throw; } }); return(_source.Send(clientPipe, cancellationToken)); }
Task ISendTransport.Send <T>(T message, IPipe <SendContext <T> > pipe, CancellationToken cancellationToken) { IPipe <SendEndpointContext> clientPipe = Pipe.ExecuteAsync <SendEndpointContext>(async clientContext => { var context = new AzureServiceBusSendContext <T>(message, cancellationToken); try { await pipe.Send(context).ConfigureAwait(false); if (message is CancelScheduledMessage cancelScheduledMessage && (context.TryGetScheduledMessageId(out var sequenceNumber) || context.TryGetSequencyNumber(cancelScheduledMessage.TokenId, out sequenceNumber))) { try { await clientContext.CancelScheduledSend(sequenceNumber).ConfigureAwait(false); if (_log.IsDebugEnabled) { _log.DebugFormat("Canceled Scheduled: {0} {1}", sequenceNumber, clientContext.EntityPath); } } catch (MessageNotFoundException exception) { if (_log.IsDebugEnabled) { _log.DebugFormat("The scheduled message was not found: {0}", exception.Message); } } return; } await _observers.PreSend(context).ConfigureAwait(false); var brokeredMessage = CreateBrokeredMessage(context); if (context.ScheduledEnqueueTimeUtc.HasValue && context.ScheduledEnqueueTimeUtc.Value < DateTime.UtcNow) { var enqueueTimeUtc = context.ScheduledEnqueueTimeUtc.Value; try { sequenceNumber = await clientContext.ScheduleSend(brokeredMessage, enqueueTimeUtc).ConfigureAwait(false); } catch (ArgumentOutOfRangeException exception) { brokeredMessage = CreateBrokeredMessage(context); await clientContext.Send(brokeredMessage).ConfigureAwait(false); sequenceNumber = 0; } context.SetScheduledMessageId(sequenceNumber); context.LogScheduled(enqueueTimeUtc); } else { await clientContext.Send(brokeredMessage).ConfigureAwait(false); context.LogSent(); await _observers.PostSend(context).ConfigureAwait(false); } } catch (Exception ex) { await _observers.SendFault(context, ex).ConfigureAwait(false); throw; } }); return(_source.Send(clientPipe, cancellationToken)); }
Task ISendTransport.Send <T>(T message, IPipe <SendContext <T> > pipe, CancellationToken cancellationToken) { IPipe <SendEndpointContext> clientPipe = Pipe.ExecuteAsync <SendEndpointContext>(async clientContext => { var context = new AzureServiceBusSendContext <T>(message, cancellationToken); try { await pipe.Send(context).ConfigureAwait(false); if (message is CancelScheduledMessage cancelScheduledMessage && (context.TryGetScheduledMessageId(out var sequenceNumber) || context.TryGetSequencyNumber(cancelScheduledMessage.TokenId, out sequenceNumber))) { try { await clientContext.CancelScheduledSend(sequenceNumber).ConfigureAwait(false); if (_log.IsDebugEnabled) { _log.DebugFormat("Canceled Scheduled: {0} {1}", sequenceNumber, clientContext.EntityPath); } } catch (MessageNotFoundException exception) { if (_log.IsDebugEnabled) { _log.DebugFormat("The scheduled message was not found: {0}", exception.Detail.Message); } } return; } await _observers.PreSend(context).ConfigureAwait(false); using (var messageBodyStream = context.GetBodyStream()) using (var brokeredMessage = new BrokeredMessage(messageBodyStream)) { brokeredMessage.ContentType = context.ContentType.MediaType; brokeredMessage.ForcePersistence = context.Durable; KeyValuePair <string, object>[] headers = context.Headers.GetAll() .Where(x => x.Value != null && (x.Value is string || x.Value.GetType().IsValueType)) .ToArray(); foreach (KeyValuePair <string, object> header in headers) { if (brokeredMessage.Properties.ContainsKey(header.Key)) { continue; } brokeredMessage.Properties.Add(header.Key, header.Value); } if (context.TimeToLive.HasValue) { brokeredMessage.TimeToLive = context.TimeToLive.Value; } if (context.MessageId.HasValue) { brokeredMessage.MessageId = context.MessageId.Value.ToString("N"); } if (context.CorrelationId.HasValue) { brokeredMessage.CorrelationId = context.CorrelationId.Value.ToString("N"); } CopyIncomingIdentifiersIfPresent(context); if (context.PartitionKey != null) { brokeredMessage.PartitionKey = context.PartitionKey; } var sessionId = string.IsNullOrWhiteSpace(context.SessionId) ? context.ConversationId?.ToString("N") : context.SessionId; if (!string.IsNullOrWhiteSpace(sessionId)) { brokeredMessage.SessionId = sessionId; if (context.ReplyToSessionId == null) { brokeredMessage.ReplyToSessionId = sessionId; } } if (context.ReplyToSessionId != null) { brokeredMessage.ReplyToSessionId = context.ReplyToSessionId; } if (context.ScheduledEnqueueTimeUtc.HasValue) { var enqueueTimeUtc = context.ScheduledEnqueueTimeUtc.Value; sequenceNumber = await clientContext.ScheduleSend(brokeredMessage, enqueueTimeUtc).ConfigureAwait(false); context.SetScheduledMessageId(sequenceNumber); context.LogScheduled(enqueueTimeUtc); } else { await clientContext.Send(brokeredMessage).ConfigureAwait(false); context.LogSent(); await _observers.PostSend(context).ConfigureAwait(false); } } } catch (Exception ex) { await _observers.SendFault(context, ex).ConfigureAwait(false); throw; } }); return(_source.Send(clientPipe, cancellationToken)); }