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); StartedActivity?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) { State <TInstance> 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(); } }
public async Task Send(ConsumeContext <RoutingSlip> context, IPipe <ConsumeContext <RoutingSlip> > next) { StartedActivity?activity = LogContext.IfEnabled(OperationName.Courier.Compensate)?.StartCompensateActivity <TActivity, TLog>(context); var timer = Stopwatch.StartNew(); try { CompensateContext <TLog> compensateContext = new HostCompensateContext <TLog>(context); LogContext.Debug?.Log("Compensate Activity: {TrackingNumber} ({Activity}, {Host})", compensateContext.TrackingNumber, TypeMetadataCache <TActivity> .ShortName, context.ReceiveContext.InputAddress); try { await Task.Yield(); await _compensatePipe.Send(compensateContext).ConfigureAwait(false); var result = compensateContext.Result ?? compensateContext.Failed(new ActivityCompensationException("The activity compensation did not return a result")); await result.Evaluate().ConfigureAwait(false); } catch (Exception ex) { await compensateContext.Failed(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 canceled 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} compensation faulted", TypeMetadataCache <TActivity> .ShortName); throw; } finally { activity?.Stop(); } }
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); } }
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(); } }
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 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); 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(); } }
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(); } }
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) { StartedActivity?activity = LogContext.IfEnabled(OperationName.Saga.SendQuery)?.StartSagaActivity <TSaga, TMessage>(context); var timer = Stopwatch.StartNew(); try { if (_queryFactory.TryCreateQuery(context, out ISagaQuery <TSaga> query)) { await Task.Yield(); await _sagaRepository.SendQuery(context, query, _policy, _messagePipe).ConfigureAwait(false); await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName).ConfigureAwait(false); } await next.Send(context).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 canceled by the consumer: {TypeMetadataCache<TSaga>.ShortName}"); } catch (Exception ex) { await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TSaga> .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(); } }
async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { StartedActivity?activity = LogContext.IfEnabled(OperationName.Consumer.Consume)?.StartConsumerActivity <TConsumer, TMessage>(context); var timer = Stopwatch.StartNew(); try { await Task.Yield(); await _instancePipe.Send(new ConsumerConsumeContextScope <TConsumer, TMessage>(context, _instance)).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 canceled by the consumer: {TypeMetadataCache<TConsumer>.ShortName}"); } catch (Exception ex) { await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TConsumer> .ShortName, ex).ConfigureAwait(false); throw; } finally { activity?.Stop(); } }
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(); } }
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(); } }
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(); 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(); } }
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(); } }