Exemple #1
0
        public async Task Send(SagaConsumeContext <TInstance, TData> context, IPipe <SagaConsumeContext <TInstance, TData> > next)
        {
            var eventContext = new StateMachineEventContextProxy <TInstance, TData>(context, _machine, context.Saga, _event, context.Message);

            var activity = LogContext.IfEnabled(OperationName.Saga.RaiseEvent)
                           ?.StartSagaActivity(context, (await _machine.Accessor.Get(eventContext).ConfigureAwait(false)).Name);

            try
            {
                await _machine.RaiseEvent(eventContext).ConfigureAwait(false);

                if (await _machine.IsCompleted(context.Saga).ConfigureAwait(false))
                {
                    await context.SetCompleted().ConfigureAwait(false);
                }
            }
            catch (UnhandledEventException ex)
            {
                var currentState = await _machine.Accessor.Get(eventContext).ConfigureAwait(false);

                throw new NotAcceptedStateMachineException(typeof(TInstance), typeof(TData), context.CorrelationId ?? Guid.Empty, currentState.Name, ex);
            }
            finally
            {
                activity?.AddTag(DiagnosticHeaders.EndState, (await _machine.Accessor.Get(eventContext).ConfigureAwait(false)).Name);
                activity?.Stop();
            }
        }
        async void HandleMessage(IMessage message)
        {
            LogContext.Current = _context.LogContext;

            if (IsStopping)
            {
                await WaitAndAbandonMessage(message).ConfigureAwait(false);

                return;
            }

            var delivery = _tracker.BeginDelivery();

            var context = new ActiveMqReceiveContext(_inputAddress, message, _context, _receiveSettings, _session, _session.ConnectionContext);

            var activity = LogContext.IfEnabled(OperationName.Transport.Receive)?.StartActivity();

            activity.AddReceiveContextHeaders(context);

            try
            {
                if (!_pending.TryAdd(message.NMSMessageId, context))
                {
                    LogContext.Warning?.Log("Duplicate message: {MessageId}", message.NMSMessageId);
                }

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PreReceive(context).ConfigureAwait(false);
                }

                await _context.ReceivePipe.Send(context).ConfigureAwait(false);

                await context.ReceiveCompleted.ConfigureAwait(false);

                message.Acknowledge();

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PostReceive(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }
            }
            finally
            {
                activity?.Stop();

                delivery.Dispose();

                _pending.TryRemove(message.NMSMessageId, out _);

                context.Dispose();
            }
        }
Exemple #3
0
        async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next)
        {
            var activity = LogContext.IfEnabled(OperationName.Consumer.Handle)?.StartHandlerActivity(context);

            Stopwatch timer = Stopwatch.StartNew();

            try
            {
                await Task.Yield();

                await _handler(context).ConfigureAwait(false);

                await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <MessageHandler <TMessage> > .ShortName).ConfigureAwait(false);

                Interlocked.Increment(ref _completed);

                await next.Send(context).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <MessageHandler <TMessage> > .ShortName, ex).ConfigureAwait(false);

                Interlocked.Increment(ref _faulted);
                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
        public async Task HandleMessage(Message message)
        {
            if (IsStopping)
            {
                await WaitAndAbandonMessage().ConfigureAwait(false);

                return;
            }

            var redelivered = message.Attributes.TryGetValue("ApproximateReceiveCount", out var receiveCountStr) &&
                              int.TryParse(receiveCountStr, out var receiveCount) && receiveCount > 1;

            var delivery = _tracker.BeginDelivery();

            var context = new AmazonSqsReceiveContext(message, redelivered, _context, _receiveSettings, _client, _client.ConnectionContext);

            var activity = LogContext.IfEnabled(OperationName.Transport.Receive)?.StartReceiveActivity(context);

            try
            {
                if (!_pending.TryAdd(message.MessageId, context))
                {
                    LogContext.Error?.Log("Duplicate message: {MessageId}", message.MessageId);
                }

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PreReceive(context).ConfigureAwait(false);
                }

                await _context.ReceivePipe.Send(context).ConfigureAwait(false);

                await context.ReceiveCompleted.ConfigureAwait(false);

                await _client.DeleteMessage(_receiveSettings.EntityName, message.ReceiptHandle).ConfigureAwait(false);

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PostReceive(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }
            }
            finally
            {
                activity?.Stop();

                delivery.Dispose();

                _pending.TryRemove(message.MessageId, out _);

                context.Dispose();
            }
        }
Exemple #5
0
        public async Task Send(ConsumeContext <RoutingSlip> context, IPipe <ConsumeContext <RoutingSlip> > next)
        {
            var activity = LogContext.IfEnabled(OperationName.Courier.Execute)?.StartExecuteActivity <TActivity, TArguments>(context);

            var timer = Stopwatch.StartNew();

            try
            {
                ExecuteContext <TArguments> executeContext = new HostExecuteContext <TArguments>(_compensateAddress, context);

                LogContext.Debug?.Log("Execute Activity: {TrackingNumber} ({Activity}, {Host})", executeContext.TrackingNumber,
                                      TypeMetadataCache <TActivity> .ShortName, context.ReceiveContext.InputAddress);

                try
                {
                    await Task.Yield();

                    await _executePipe.Send(executeContext).ConfigureAwait(false);

                    var result = executeContext.Result
                                 ?? executeContext.Faulted(new ActivityExecutionException("The activity execute did not return a result"));

                    await result.Evaluate().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    await executeContext.Faulted(ex).Evaluate().ConfigureAwait(false);
                }

                await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <TActivity> .ShortName).ConfigureAwait(false);

                await next.Send(context).ConfigureAwait(false);
            }
            catch (OperationCanceledException exception)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TActivity> .ShortName, exception).ConfigureAwait(false);

                if (exception.CancellationToken == context.CancellationToken)
                {
                    throw;
                }

                throw new ConsumerCanceledException($"The operation was cancelled by the activity: {TypeMetadataCache<TActivity>.ShortName}");
            }
            catch (Exception ex)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TActivity> .ShortName, ex).ConfigureAwait(false);

                LogContext.Error?.Log(ex, "Activity {Activity} execution faulted: {Exception}", TypeMetadataCache <TActivity> .ShortName);

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
Exemple #6
0
        public async Task Dispatch(ReceiveContext context, ReceiveLockContext receiveLock = default)
        {
            LogContext.Current = _logContext;

            var active = StartDispatch();

            StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Receive)?.StartReceiveActivity(context);

            try
            {
                if (_observers.Count > 0)
                {
                    await _observers.PreReceive(context).ConfigureAwait(false);
                }

                if (receiveLock != null)
                {
                    await receiveLock.ValidateLockStatus().ConfigureAwait(false);
                }

                await _receivePipe.Send(context).ConfigureAwait(false);

                await context.ReceiveCompleted.ConfigureAwait(false);

                if (receiveLock != null)
                {
                    await receiveLock.Complete().ConfigureAwait(false);
                }

                if (_observers.Count > 0)
                {
                    await _observers.PostReceive(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_observers.Count > 0)
                {
                    await _observers.ReceiveFault(context, ex).ConfigureAwait(false);
                }

                if (receiveLock != null)
                {
                    await receiveLock.Faulted(ex).ConfigureAwait(false);
                }

                throw;
            }
            finally
            {
                activity?.Stop();

                await active.Complete().ConfigureAwait(false);
            }
        }
Exemple #7
0
            public async Task Send(ClientContext clientContext)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(clientContext).ConfigureAwait(false);

                var context = new TransportAmazonSqsSendContext <T>(_message, _cancellationToken);

                var activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartActivity(new { _context.EntityName });

                try
                {
                    await _pipe.Send(context).ConfigureAwait(false);

                    activity.AddSendContextHeaders(context);

                    var request = clientContext.CreatePublishRequest(_context.EntityName, context.Body);

                    _context.SnsSetHeaderAdapter.Set(request.MessageAttributes, context.Headers);

                    _context.SnsSetHeaderAdapter.Set(request.MessageAttributes, "Content-Type", context.ContentType.MediaType);
                    _context.SnsSetHeaderAdapter.Set(request.MessageAttributes, nameof(context.CorrelationId), context.CorrelationId);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                    }

                    await clientContext.Publish(request, context.CancellationToken).ConfigureAwait(false);

                    context.LogSent();

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    context.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #8
0
        async Task ISendTransport.Send <T>(T message, IPipe <SendContext <T> > pipe, CancellationToken cancellationToken)
        {
            LogContext.SetCurrentIfNull(_context.LogContext);

            var context = new MessageSendContext <T>(message, cancellationToken);

            await pipe.Send(context).ConfigureAwait(false);

            StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context);

            try
            {
                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                }

                var messageId = context.MessageId ?? NewId.NextGuid();

                var transportMessage = new InMemoryTransportMessage(messageId, context.Body, context.ContentType.MediaType,
                                                                    TypeMetadataCache <T> .ShortName)
                {
                    Delay = context.Delay
                };

                SetHeaders(transportMessage.Headers, context.Headers);

                await _context.Exchange.Send(transportMessage, cancellationToken).ConfigureAwait(false);

                context.LogSent();
                activity.AddSendContextHeadersPostSend(context);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                context.LogFaulted(ex);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                }

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
Exemple #9
0
        public async Task Consume(InMemoryTransportMessage message, CancellationToken cancellationToken)
        {
            await Ready.ConfigureAwait(false);

            if (IsStopped)
            {
                return;
            }

            LogContext.Current = _context.LogContext;

            var context  = new InMemoryReceiveContext(_inputAddress, message, _context);
            var delivery = _tracker.BeginDelivery();

            var activity = LogContext.IfEnabled(OperationName.Transport.Receive)?.StartActivity();

            activity.AddReceiveContextHeaders(context);

            try
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PreReceive(context).ConfigureAwait(false);
                }

                await _context.ReceivePipe.Send(context).ConfigureAwait(false);

                await context.ReceiveCompleted.ConfigureAwait(false);

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PostReceive(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }

                message.DeliveryCount++;
            }
            finally
            {
                activity?.Stop();

                delivery.Dispose();

                context.Dispose();
            }
        }
            public async Task Send(SagaConsumeContext <TSaga, TMessage> context)
            {
                var instance = new SagaInstance <TSaga>(context.Saga);

                await instance.MarkInUse(context.CancellationToken).ConfigureAwait(false);

                var activity = LogContext.IfEnabled(OperationName.Saga.Add)?.StartActivity(new { context.Saga.CorrelationId });

                try
                {
                    var sagaConsumeContext = new InMemorySagaConsumeContext <TSaga, TMessage>(context, context.Saga,
                                                                                              () => RemoveNewSaga(instance, context.CancellationToken));

                    if (_withinLock)
                    {
                        _repository.AddWithinLock(instance);
                    }
                    else
                    {
                        await _repository.Add(instance, context.CancellationToken).ConfigureAwait(false);
                    }

                    sagaConsumeContext.LogAdded();

                    try
                    {
                        await _next.Send(sagaConsumeContext).ConfigureAwait(false);

                        if (sagaConsumeContext.IsCompleted)
                        {
                            await RemoveNewSaga(instance, context.CancellationToken).ConfigureAwait(false);

                            sagaConsumeContext.LogRemoved();
                        }
                    }
                    catch (Exception exception)
                    {
                        await RemoveNewSaga(instance, context.CancellationToken).ConfigureAwait(false);

                        sagaConsumeContext.LogRemoved(exception);

                        throw;
                    }
                }
                finally
                {
                    instance.Release();

                    activity?.Stop();
                }
            }
Exemple #11
0
        public async Task Send(SagaConsumeContext <TSaga, TMessage> context, IPipe <SagaConsumeContext <TSaga, TMessage> > next)
        {
            StartedActivity?activity = LogContext.IfEnabled(OperationName.Saga.InitiateOrOrchestrate)?.StartSagaActivity(context);

            try
            {
                await context.Saga.Consume(context).ConfigureAwait(false);

                await next.Send(context).ConfigureAwait(false);
            }
            finally
            {
                activity?.Stop();
            }
        }
        public async Task Send(SagaConsumeContext <TSaga, TMessage> context, IPipe <SagaConsumeContext <TSaga, TMessage> > next)
        {
            var activity = LogContext.IfEnabled(OperationName.Saga.Observe)?.StartSagaActivity <TSaga, TMessage>(context.Saga.CorrelationId);

            try
            {
                await context.Saga.Consume(context).ConfigureAwait(false);

                await next.Send(context).ConfigureAwait(false);
            }
            finally
            {
                activity?.Stop();
            }
        }
        async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            if (!context.TryGetPayload(out MessageSessionContext sessionContext))
            {
                throw new SagaException($"The session-based saga repository requires an active message session: {TypeMetadataCache<TSaga>.ShortName}",
                                        typeof(TSaga), typeof(T));
            }

            if (Guid.TryParse(sessionContext.SessionId, out var sessionId))
            {
                context = new CorrelationIdConsumeContextProxy <T>(context, sessionId);
            }

            StartedActivity?activity = LogContext.IfEnabled(OperationName.Saga.Send)?.StartSagaActivity <TSaga, T>(context);

            try
            {
                var saga = await ReadSagaState(sessionContext).ConfigureAwait(false);

                if (saga == null)
                {
                    var missingSagaPipe = new MissingPipe <T>(next, WriteSagaState);

                    await policy.Missing(context, missingSagaPipe).ConfigureAwait(false);
                }
                else
                {
                    SagaConsumeContext <TSaga, T> sagaConsumeContext = new MessageSessionSagaConsumeContext <TSaga, T>(context, sessionContext, saga);

                    LogContext.Debug?.Log("SAGA:{SagaType}:{CorrelationId} Used {MessageType}", TypeMetadataCache <TSaga> .ShortName,
                                          context.CorrelationId, TypeMetadataCache <T> .ShortName);

                    await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false);

                    if (!sagaConsumeContext.IsCompleted)
                    {
                        await WriteSagaState(sessionContext, saga).ConfigureAwait(false);

                        LogContext.Debug?.Log("SAGA:{SagaType}:{CorrelationId} Updated {MessageType}", TypeMetadataCache <TSaga> .ShortName,
                                              context.CorrelationId, TypeMetadataCache <T> .ShortName);
                    }
                }
            }
            finally
            {
                activity?.Stop();
            }
        }
        async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next)
        {
            Stopwatch timer = Stopwatch.StartNew();

            var activity = LogContext.IfEnabled(OperationName.Saga.SendQuery)?.StartActivity(new
            {
                SagaType    = TypeMetadataCache <TSaga> .ShortName,
                MessageType = TypeMetadataCache <TMessage> .ShortName
            });

            try
            {
                ISagaQuery <TSaga> query = _queryFactory.CreateQuery(context);

                SagaQueryConsumeContext <TSaga, TMessage> queryContext = new SagaQueryConsumeContextScope <TSaga, TMessage>(context, query);

                await Task.Yield();

                await _sagaRepository.SendQuery(queryContext, _policy, _messagePipe).ConfigureAwait(false);

                await next.Send(context).ConfigureAwait(false);

                await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName).ConfigureAwait(false);
            }
            catch (OperationCanceledException exception)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName, exception).ConfigureAwait(false);

                if (exception.CancellationToken == context.CancellationToken)
                {
                    throw;
                }

                throw new ConsumerCanceledException($"The operation was cancelled by the consumer: {TypeMetadataCache<TSaga>.ShortName}");
            }
            catch (Exception ex)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName, ex).ConfigureAwait(false);

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
Exemple #15
0
        async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next)
        {
            var activity = LogContext.IfEnabled(OperationName.Consumer.Consume)?.StartActivity(new
            {
                ConsumerType = TypeMetadataCache <TConsumer> .ShortName,
                MessageType  = TypeMetadataCache <TMessage> .ShortName
            });

            var timer = Stopwatch.StartNew();

            try
            {
                await Task.Yield();

                await _consumerFactory.Send(context, _consumerPipe).ConfigureAwait(false);

                await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <TConsumer> .ShortName).ConfigureAwait(false);

                await next.Send(context).ConfigureAwait(false);
            }
            catch (OperationCanceledException exception)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TConsumer> .ShortName, exception).ConfigureAwait(false);

                if (exception.CancellationToken == context.CancellationToken)
                {
                    throw;
                }

                throw new ConsumerCanceledException($"The operation was cancelled by the consumer: {TypeMetadataCache<TConsumer>.ShortName}");
            }
            catch (Exception ex)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TConsumer> .ShortName, ex).ConfigureAwait(false);

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
        async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next)
        {
            StartedActivity?activity = LogContext.IfEnabled(OperationName.Consumer.Handle)?.StartHandlerActivity(context);

            var timer = Stopwatch.StartNew();

            try
            {
                await Task.Yield();

                await _handler(context).ConfigureAwait(false);

                await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <MessageHandler <TMessage> > .ShortName).ConfigureAwait(false);

                Interlocked.Increment(ref _completed);

                await next.Send(context).ConfigureAwait(false);
            }
            catch (OperationCanceledException exception)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <MessageHandler <TMessage> > .ShortName, exception).ConfigureAwait(false);

                if (exception.CancellationToken == context.CancellationToken)
                {
                    throw;
                }

                throw new ConsumerCanceledException($"The operation was canceled by the consumer: {TypeMetadataCache<MessageHandler<TMessage>>.ShortName}");
            }
            catch (Exception ex)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <MessageHandler <TMessage> > .ShortName, ex).ConfigureAwait(false);

                Interlocked.Increment(ref _faulted);
                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
Exemple #17
0
            public async Task Send(SessionContext sessionContext)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(sessionContext).ConfigureAwait(false);

                var destination = await sessionContext.GetDestination(_context.EntityName, _context.DestinationType).ConfigureAwait(false);

                var producer = await sessionContext.CreateMessageProducer(destination).ConfigureAwait(false);

                var context = new TransportActiveMqSendContext <T>(_message, _cancellationToken);

                await _pipe.Send(context).ConfigureAwait(false);

                StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context);

                try
                {
                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                    }

                    var transportMessage = sessionContext.Session.CreateBytesMessage();

                    transportMessage.Properties.SetHeaders(context.Headers);

                    transportMessage.Properties["Content-Type"] = context.ContentType.MediaType;

                    transportMessage.NMSDeliveryMode = context.Durable ? MsgDeliveryMode.Persistent : MsgDeliveryMode.NonPersistent;

                    if (context.MessageId.HasValue)
                    {
                        transportMessage.NMSMessageId = context.MessageId.ToString();
                    }

                    if (context.CorrelationId.HasValue)
                    {
                        transportMessage.NMSCorrelationID = context.CorrelationId.ToString();
                    }

                    if (context.TimeToLive.HasValue)
                    {
                        transportMessage.NMSTimeToLive = context.TimeToLive > TimeSpan.Zero ? context.TimeToLive.Value : TimeSpan.FromSeconds(1);
                    }

                    if (context.Priority.HasValue)
                    {
                        transportMessage.NMSPriority = context.Priority.Value;
                    }

                    transportMessage.Content = context.Body;

                    var publishTask = Task.Run(() => producer.Send(transportMessage), context.CancellationToken);

                    await publishTask.OrCanceled(context.CancellationToken).ConfigureAwait(false);

                    context.LogSent();
                    activity.AddSendContextHeadersPostSend(context);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    context.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #18
0
            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();
                }
            }
            public async Task Send(ModelContext modelContext)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(modelContext).ConfigureAwait(false);

                var properties = modelContext.Model.CreateBasicProperties();

                var context = new BasicPublishRabbitMqSendContext <T>(properties, _context.Exchange, _message, _cancellationToken);

                await _pipe.Send(context).ConfigureAwait(false);

                var exchange = context.Exchange;

                if (exchange.Equals(RabbitMqExchangeNames.ReplyTo))
                {
                    if (string.IsNullOrWhiteSpace(context.RoutingKey))
                    {
                        throw new TransportException(context.DestinationAddress, "RoutingKey must be specified when sending to reply-to address");
                    }

                    exchange = "";
                }

                StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context);

                try
                {
                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                    }

                    byte[] body = context.Body;

                    if (context.TryGetPayload(out PublishContext publishContext))
                    {
                        context.Mandatory = context.Mandatory || publishContext.Mandatory;
                    }

                    properties.Headers ??= new Dictionary <string, object>();

                    properties.ContentType = context.ContentType.MediaType;

                    properties.Headers["Content-Type"] = context.ContentType.MediaType;

                    SetHeaders(properties.Headers, context.Headers);

                    properties.Persistent = context.Durable;

                    if (context.MessageId.HasValue)
                    {
                        properties.MessageId = context.MessageId.ToString();
                    }

                    if (context.CorrelationId.HasValue)
                    {
                        properties.CorrelationId = context.CorrelationId.ToString();
                    }

                    if (context.TimeToLive.HasValue)
                    {
                        properties.Expiration = (context.TimeToLive > TimeSpan.Zero ? context.TimeToLive.Value : TimeSpan.FromSeconds(1)).TotalMilliseconds
                                                .ToString("F0", CultureInfo.InvariantCulture);
                    }

                    if (context.RequestId.HasValue && (context.ResponseAddress?.AbsolutePath?.EndsWith(RabbitMqExchangeNames.ReplyTo) ?? false))
                    {
                        context.BasicProperties.ReplyTo = RabbitMqExchangeNames.ReplyTo;
                    }

                    var publishTask = modelContext.BasicPublishAsync(exchange, context.RoutingKey ?? "", context.Mandatory, context.BasicProperties, body,
                                                                     context.AwaitAck);

                    await publishTask.OrCanceled(context.CancellationToken).ConfigureAwait(false);

                    context.LogSent();
                    activity.AddSendContextHeadersPostSend(context);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    context.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #20
0
            public async Task Send(ProducerContext context)
            {
                if (_messages == null)
                {
                    throw new ArgumentNullException(nameof(_messages));
                }

                LogContext.SetCurrentIfNull(_context.LogContext);

                EventHubMessageSendContext <T>[] contexts = _messages
                                                            .Select(x => new EventHubMessageSendContext <T>(x, _cancellationToken)
                {
                    Serializer = context.Serializer
                })
                                                            .ToArray();

                if (contexts.Length == 0)
                {
                    return;
                }

                NewId[] ids = NewId.Next(contexts.Length);

                async Task SendInner(EventHubMessageSendContext <T> c, int idx)
                {
                    c.DestinationAddress = _context.EndpointAddress;

                    await _context.SendPipe.Send(c).ConfigureAwait(false);

                    if (_pipe.IsNotEmpty())
                    {
                        await _pipe.Send(c).ConfigureAwait(false);
                    }

                    c.SourceAddress ??= _context.HostAddress;
                    c.ConversationId ??= ids[idx].ToGuid();
                }

                await Task.WhenAll(contexts.Select(SendInner)).ConfigureAwait(false);

                EventHubMessageSendContext <T> sendContext = contexts[0];
                var options = new CreateBatchOptions
                {
                    PartitionId  = sendContext.PartitionId,
                    PartitionKey = sendContext.PartitionKey
                };

                StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(sendContext,
                                                                                                                 (nameof(EventHubMessageSendContext <T> .PartitionId), options.PartitionId),
                                                                                                                 (nameof(EventHubMessageSendContext <T> .PartitionKey), options.PartitionKey));

                try
                {
                    var eventDataBatch = await context.CreateBatch(options, context.CancellationToken).ConfigureAwait(false);

                    if (_context.SendObservers.Count > 0)
                    {
                        await Task.WhenAll(contexts.Select(c => _context.SendObservers.PreSend(c))).ConfigureAwait(false);
                    }

                    async Task FlushAsync(EventDataBatch batch)
                    {
                        await context.Produce(batch, context.CancellationToken).ConfigureAwait(false);

                        batch.Dispose();
                    }

                    for (var i = 0; i < contexts.Length; i++)
                    {
                        EventHubMessageSendContext <T> c = contexts[i];

                        var eventData = new EventData(c.Body);

                        eventData.Properties.Set(c.Headers);

                        while (!eventDataBatch.TryAdd(eventData) && eventDataBatch.Count > 0)
                        {
                            await FlushAsync(eventDataBatch);

                            eventDataBatch = await context.CreateBatch(options, context.CancellationToken).ConfigureAwait(false);
                        }
                    }

                    if (eventDataBatch.Count > 0)
                    {
                        await FlushAsync(eventDataBatch);
                    }

                    sendContext.LogSent();
                    activity.AddSendContextHeadersPostSend(sendContext);

                    if (_context.SendObservers.Count > 0)
                    {
                        await Task.WhenAll(contexts.Select(c => _context.SendObservers.PostSend(c))).ConfigureAwait(false);
                    }
                }
                catch (Exception exception)
                {
                    sendContext.LogFaulted(exception);

                    if (_context.SendObservers.Count > 0)
                    {
                        await Task.WhenAll(contexts.Select(c => _context.SendObservers.SendFault(c, exception))).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #21
0
            public async Task Send(ProducerContext context)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                var sendContext = new EventHubMessageSendContext <T>(_message, _cancellationToken)
                {
                    Serializer         = context.Serializer,
                    DestinationAddress = _context.EndpointAddress
                };

                await _context.SendPipe.Send(sendContext).ConfigureAwait(false);

                if (_pipe.IsNotEmpty())
                {
                    await _pipe.Send(sendContext).ConfigureAwait(false);
                }

                sendContext.SourceAddress ??= _context.HostAddress;
                sendContext.ConversationId ??= NewId.NextGuid();

                var options = new SendEventOptions
                {
                    PartitionId  = sendContext.PartitionId,
                    PartitionKey = sendContext.PartitionKey
                };

                StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(sendContext,
                                                                                                                 (nameof(sendContext.PartitionId), options.PartitionId), (nameof(sendContext.PartitionKey), options.PartitionKey));

                try
                {
                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(sendContext).ConfigureAwait(false);
                    }

                    var eventData = new EventData(sendContext.Body);

                    eventData.Properties.Set(sendContext.Headers);

                    await context.Produce(new[] { eventData }, options, sendContext.CancellationToken).ConfigureAwait(false);

                    sendContext.LogSent();
                    activity.AddSendContextHeadersPostSend(sendContext);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(sendContext).ConfigureAwait(false);
                    }
                }
                catch (Exception exception)
                {
                    sendContext.LogFaulted(exception);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(sendContext, exception).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #22
0
            public async Task Send(ClientContext context)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(context).ConfigureAwait(false);

                var sendContext = new AmazonSqsMessageSendContext <T>(_message, _cancellationToken);

                await _pipe.Send(sendContext).ConfigureAwait(false);

                StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(sendContext);

                try
                {
                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(sendContext).ConfigureAwait(false);
                    }

                    var request = await context.CreatePublishRequest(_context.EntityName, sendContext.Body).ConfigureAwait(false);

                    _context.SnsSetHeaderAdapter.Set(request.MessageAttributes, sendContext.Headers);

                    _context.SnsSetHeaderAdapter.Set(request.MessageAttributes, "Content-Type", sendContext.ContentType.MediaType);
                    _context.SnsSetHeaderAdapter.Set(request.MessageAttributes, nameof(sendContext.CorrelationId), sendContext.CorrelationId);

                    if (!string.IsNullOrEmpty(sendContext.DeduplicationId))
                    {
                        request.MessageDeduplicationId = sendContext.DeduplicationId;
                    }

                    if (!string.IsNullOrEmpty(sendContext.GroupId))
                    {
                        request.MessageGroupId = sendContext.GroupId;
                    }

                    await context.Publish(request, sendContext.CancellationToken).ConfigureAwait(false);

                    sendContext.LogSent();
                    activity.AddSendContextHeadersPostSend(sendContext);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(sendContext).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    sendContext.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(sendContext, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #23
0
            public async Task Send(ClientContext clientContext)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(clientContext).ConfigureAwait(false);

                var context = new TransportAmazonSqsSendContext <T>(_message, _cancellationToken);

                await _pipe.Send(context).ConfigureAwait(false);

                var activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context);

                try
                {
                    var request = clientContext.CreateSendRequest(_context.EntityName, context.Body);

                    _context.SqsSetHeaderAdapter.Set(request.MessageAttributes, context.Headers);

                    _context.SqsSetHeaderAdapter.Set(request.MessageAttributes, "Content-Type", context.ContentType.MediaType);
                    _context.SqsSetHeaderAdapter.Set(request.MessageAttributes, nameof(context.CorrelationId), context.CorrelationId);

                    if (!string.IsNullOrEmpty(context.DeduplicationId))
                    {
                        request.MessageDeduplicationId = context.DeduplicationId;
                    }

                    if (!string.IsNullOrEmpty(context.GroupId))
                    {
                        request.MessageGroupId = context.GroupId;
                    }

                    if (context.DelaySeconds.HasValue)
                    {
                        request.DelaySeconds = context.DelaySeconds.Value;
                    }

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                    }

                    await clientContext.SendMessage(request, context.CancellationToken).ConfigureAwait(false);

                    context.LogSent();

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    context.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
Exemple #24
0
        public async Task Produce(TKey key, TValue value, IPipe <KafkaSendContext <TKey, TValue> > pipe, CancellationToken cancellationToken)
        {
            LogContext.SetCurrentIfNull(_context.LogContext);

            var context = new KafkaMessageSendContext <TKey, TValue>(key, value, cancellationToken);

            if (_consumeContext != null)
            {
                context.TransferConsumeContextHeaders(_consumeContext);
            }

            context.DestinationAddress = _topicAddress;

            await _context.Send(context).ConfigureAwait(false);

            if (pipe.IsNotEmpty())
            {
                await pipe.Send(context).ConfigureAwait(false);
            }

            context.SourceAddress ??= _context.HostAddress;
            context.ConversationId ??= NewId.NextGuid();

            StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context,
                                                                                                             (nameof(context.Partition), context.Partition.ToString()));

            try
            {
                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                }

                var message = new Message <TKey, TValue>
                {
                    Key   = context.Key,
                    Value = context.Message
                };

                if (context.SentTime.HasValue)
                {
                    message.Timestamp = new Timestamp(context.SentTime.Value);
                }

                message.Headers = _context.HeadersSerializer.Serialize(context);

                var topic = new TopicPartition(_topicAddress.Topic, context.Partition);

                await _context.Produce(topic, message, context.CancellationToken).ConfigureAwait(false);

                context.LogSent();
                activity.AddSendContextHeadersPostSend(context);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                }
            }
            catch (Exception exception)
            {
                context.LogFaulted(exception);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.SendFault(context, exception).ConfigureAwait(false);
                }

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
Exemple #25
0
        async void IBasicConsumer.HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange,
                                                     string routingKey,
                                                     IBasicProperties properties, byte[] body)
        {
            LogContext.Current = _context.LogContext;

            if (IsStopping && _receiveSettings.NoAck == false)
            {
                await WaitAndAbandonMessage(deliveryTag).ConfigureAwait(false);

                return;
            }

            var delivery = _tracker.BeginDelivery();

            var context = new RabbitMqReceiveContext(exchange, routingKey, _consumerTag, deliveryTag, body, redelivered, properties, _context, _receiveSettings,
                                                     _model, _model.ConnectionContext);

            var activity = LogContext.IfEnabled(OperationName.Transport.Receive)?.StartReceiveActivity(context);

            try
            {
                if (!_pending.TryAdd(deliveryTag, context))
                {
                    LogContext.Warning?.Log("Duplicate BasicDeliver: {DeliveryTag}", deliveryTag);
                }

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PreReceive(context).ConfigureAwait(false);
                }

                await _context.ReceivePipe.Send(context).ConfigureAwait(false);

                await context.ReceiveCompleted.ConfigureAwait(false);

                if (_receiveSettings.NoAck == false)
                {
                    _model.BasicAck(deliveryTag, false);
                }

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PostReceive(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }

                try
                {
                    if (_receiveSettings.NoAck == false)
                    {
                        _model.BasicNack(deliveryTag, false, true);
                    }
                }
                catch (Exception ackEx)
                {
                    LogContext.Error?.Log(ackEx, "Message NACK failed: {DeliveryTag}", deliveryTag);
                }
            }
            finally
            {
                activity?.Stop();

                delivery.Dispose();

                _pending.TryRemove(deliveryTag, out _);
                context.Dispose();
            }
        }
Exemple #26
0
        public async Task Produce <T>(T message, IPipe <EventHubSendContext <T> > pipe, CancellationToken cancellationToken)
            where T : class
        {
            LogContext.SetCurrentIfNull(_context.LogContext);

            var context = new EventHubMessageSendContext <T>(message, cancellationToken)
            {
                Serializer = _context.Serializer
            };

            if (_consumeContext != null)
            {
                context.TransferConsumeContextHeaders(_consumeContext);
            }

            context.DestinationAddress = _topicAddress;

            await _context.Send(context).ConfigureAwait(false);

            if (pipe.IsNotEmpty())
            {
                await pipe.Send(context).ConfigureAwait(false);
            }

            context.SourceAddress ??= _context.HostAddress;
            context.ConversationId ??= NewId.NextGuid();

            var options = new SendEventOptions
            {
                PartitionId  = context.PartitionId,
                PartitionKey = context.PartitionKey
            };

            StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context,
                                                                                                             (nameof(context.PartitionId), options.PartitionId), (nameof(context.PartitionKey), options.PartitionKey));

            try
            {
                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                }

                var eventData = new EventData(context.Body);

                eventData.Properties.Set(context.Headers);

                await _context.Produce(new[] { eventData }, options, context.CancellationToken).ConfigureAwait(false);

                context.LogSent();
                activity.AddSendContextHeadersPostSend(context);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                }
            }
            catch (Exception exception)
            {
                context.LogFaulted(exception);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.SendFault(context, exception).ConfigureAwait(false);
                }

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
        async Task IBrokeredMessageReceiver.Handle(Message message, Action <ReceiveContext> contextCallback)
        {
            LogContext.Current = _context.LogContext;

            var context = new ServiceBusReceiveContext(_inputAddress, message, _context);

            contextCallback?.Invoke(context);

            context.TryGetPayload <MessageLockContext>(out var lockContext);

            var activity = LogContext.IfEnabled(OperationName.Transport.Receive)?.StartActivity();

            activity.AddReceiveContextHeaders(context);

            try
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PreReceive(context).ConfigureAwait(false);
                }

                if (message.SystemProperties.LockedUntilUtc <= DateTime.UtcNow)
                {
                    throw new MessageLockExpiredException(_inputAddress, $"The message lock expired: {message.MessageId}");
                }

                if (message.ExpiresAtUtc < DateTime.UtcNow)
                {
                    throw new MessageTimeToLiveExpiredException(_inputAddress, $"The message TTL expired: {message.MessageId}");
                }

                await _context.ReceivePipe.Send(context).ConfigureAwait(false);

                await context.ReceiveCompleted.ConfigureAwait(false);

                if (lockContext != null)
                {
                    await lockContext.Complete().ConfigureAwait(false);
                }

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.PostReceive(context).ConfigureAwait(false);
                }
            }
            catch (SessionLockLostException ex)
            {
                LogContext.Warning?.Log(ex, "Session Lock Lost: {MessageId", message.MessageId);

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }
            }
            catch (MessageLockLostException ex)
            {
                LogContext.Warning?.Log(ex, "Session Lock Lost: {MessageId", message.MessageId);

                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                if (_context.ReceiveObservers.Count > 0)
                {
                    await _context.ReceiveObservers.ReceiveFault(context, ex).ConfigureAwait(false);
                }

                if (lockContext == null)
                {
                    throw;
                }

                try
                {
                    await lockContext.Abandon(ex).ConfigureAwait(false);
                }
                catch (Exception exception)
                {
                    LogContext.Warning?.Log(exception, "Abandon message faulted: {MessageId", message.MessageId);
                }
            }
            finally
            {
                activity?.Stop();

                context.Dispose();
            }
        }
            public async Task Send(ModelContext modelContext)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(modelContext).ConfigureAwait(false);

                var properties = modelContext.Model.CreateBasicProperties();

                var context = new BasicPublishRabbitMqSendContext <T>(properties, _context.Exchange, _message, _cancellationToken);

                await _pipe.Send(context).ConfigureAwait(false);

                var activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context);

                try
                {
                    byte[] body = context.Body;

                    if (context.TryGetPayload(out PublishContext publishContext))
                    {
                        context.Mandatory = context.Mandatory || publishContext.Mandatory;
                    }

                    if (properties.Headers == null)
                    {
                        properties.Headers = new Dictionary <string, object>();
                    }

                    properties.ContentType = context.ContentType.MediaType;

                    properties.Headers["Content-Type"] = context.ContentType.MediaType;

                    SetHeaders(properties.Headers, context.Headers);

                    properties.Persistent = context.Durable;

                    if (context.MessageId.HasValue)
                    {
                        properties.MessageId = context.MessageId.ToString();
                    }

                    if (context.CorrelationId.HasValue)
                    {
                        properties.CorrelationId = context.CorrelationId.ToString();
                    }

                    if (context.TimeToLive.HasValue)
                    {
                        properties.Expiration = context.TimeToLive.Value.TotalMilliseconds.ToString("F0", CultureInfo.InvariantCulture);
                    }

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                    }

                    var publishTask = modelContext.BasicPublishAsync(context.Exchange, context.RoutingKey ?? "", context.Mandatory,
                                                                     context.BasicProperties, body, context.AwaitAck);

                    await publishTask.OrCanceled(context.CancellationToken).ConfigureAwait(false);

                    context.LogSent();

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    context.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
            public async Task Send(ClientContext context)
            {
                LogContext.SetCurrentIfNull(_context.LogContext);

                await _context.ConfigureTopologyPipe.Send(context).ConfigureAwait(false);

                var sendContext = new TransportAmazonSqsSendContext <T>(_message, _cancellationToken);

                await _pipe.Send(sendContext).ConfigureAwait(false);

                StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(sendContext);

                try
                {
                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PreSend(sendContext).ConfigureAwait(false);
                    }

                    var message = new SendMessageBatchRequestEntry("", Encoding.UTF8.GetString(sendContext.Body));

                    _context.SqsSetHeaderAdapter.Set(message.MessageAttributes, sendContext.Headers);

                    _context.SqsSetHeaderAdapter.Set(message.MessageAttributes, "Content-Type", sendContext.ContentType.MediaType);
                    _context.SqsSetHeaderAdapter.Set(message.MessageAttributes, nameof(sendContext.CorrelationId), sendContext.CorrelationId);

                    if (!string.IsNullOrEmpty(sendContext.DeduplicationId))
                    {
                        message.MessageDeduplicationId = sendContext.DeduplicationId;
                    }

                    if (!string.IsNullOrEmpty(sendContext.GroupId))
                    {
                        message.MessageGroupId = sendContext.GroupId;
                    }

                    if (sendContext.DelaySeconds.HasValue)
                    {
                        message.DelaySeconds = sendContext.DelaySeconds.Value;
                    }

                    await context.SendMessage(_context.EntityName, message, sendContext.CancellationToken).ConfigureAwait(false);

                    sendContext.LogSent();

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.PostSend(sendContext).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    sendContext.LogFaulted(ex);

                    if (_context.SendObservers.Count > 0)
                    {
                        await _context.SendObservers.SendFault(sendContext, ex).ConfigureAwait(false);
                    }

                    throw;
                }
                finally
                {
                    activity?.Stop();
                }
            }
        async Task ISendTransport.Send <T>(T message, IPipe <SendContext <T> > pipe, CancellationToken cancellationToken)
        {
            LogContext.SetCurrentIfNull(_context.LogContext);

            var context = new TransportGrpcSendContext <T>(_context.Exchange.Name, message, cancellationToken);

            await pipe.Send(context).ConfigureAwait(false);

            StartedActivity?activity = LogContext.IfEnabled(OperationName.Transport.Send)?.StartSendActivity(context);

            try
            {
                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PreSend(context).ConfigureAwait(false);
                }

                var messageId = context.MessageId ?? NewId.NextGuid();

                var transportMessage = new TransportMessage
                {
                    Deliver = new Deliver
                    {
                        Exchange = new ExchangeDestination
                        {
                            Name       = _context.Exchange.Name,
                            RoutingKey = context.RoutingKey ?? ""
                        },
                        Envelope = new Envelope
                        {
                            MessageId          = messageId.ToString("D"),
                            RequestId          = context.RequestId?.ToString("D") ?? "",
                            ConversationId     = context.ConversationId?.ToString("D") ?? "",
                            CorrelationId      = context.CorrelationId?.ToString("D") ?? "",
                            InitiatorId        = context.InitiatorId?.ToString("D") ?? "",
                            SourceAddress      = context.SourceAddress?.ToString() ?? "",
                            DestinationAddress = context.DestinationAddress?.ToString() ?? "",
                            ResponseAddress    = context.ResponseAddress?.ToString() ?? "",
                            FaultAddress       = context.FaultAddress?.ToString() ?? "",
                            ContentType        = context.ContentType?.MediaType ?? "",
                            Body           = ByteString.CopyFrom(context.Body),
                            EnqueueTime    = context.Delay.ToFutureDateTime(),
                            ExpirationTime = context.TimeToLive.ToFutureDateTime(),
                            SentTime       = Timestamp.FromDateTime(context.SentTime ?? DateTime.UtcNow),
                        }
                    }
                };

                transportMessage.Deliver.Envelope.MessageType.AddRange(TypeMetadataCache <T> .MessageTypeNames);

                SetHeaders(transportMessage.Deliver.Envelope.Headers, context.Headers);

                var grpcTransportMessage = new GrpcTransportMessage(transportMessage, HostMetadataCache.Host);

                await _context.Exchange.Send(grpcTransportMessage, cancellationToken).ConfigureAwait(false);

                context.LogSent();
                activity.AddSendContextHeadersPostSend(context);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.PostSend(context).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                context.LogFaulted(ex);

                if (_context.SendObservers.Count > 0)
                {
                    await _context.SendObservers.SendFault(context, ex).ConfigureAwait(false);
                }

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }