コード例 #1
0
    public override async Task Invoke(IInvokeHandlerContext context, Func <Task> next)
    {
        if (!(context.MessageHandler.Instance is Saga))
        {
            // Message was not handled by the saga
            await next().ConfigureAwait(false);

            return;
        }

        var logger = context.Logger();

        if (!logger.IsEnabled(LogEventLevel.Information))
        {
            await next().ConfigureAwait(false);

            return;
        }

        sagaAudit = new SagaUpdatedMessage
        {
            StartTime = DateTimeOffset.UtcNow
        };
        context.Extensions.Set(sagaAudit);
        await next()
        .ConfigureAwait(false);

        if (context.Extensions.TryGet(out ActiveSagaInstance activeSagaInstance))
        {
            sagaAudit.SagaType = activeSagaInstance.Instance.GetType().FullName;

            sagaAudit.FinishTime = DateTimeOffset.UtcNow;
            AuditSaga(activeSagaInstance, context);
        }
    }
        public void Invoke(IncomingContext context, Action next)
        {
            var saga = context.MessageHandler.Instance as Saga;

            if (saga == null)
            {
                next();
                return;
            }

            sagaAudit = new SagaUpdatedMessage
            {
                StartTime = DateTime.UtcNow
            };
            context.Set(sagaAudit);
            next();

            if (saga.Entity == null)
            {
                return; // Message was not handled by the saga
            }

            sagaAudit.FinishTime = DateTime.UtcNow;
            AuditSaga(saga, context);
        }
    void AssignSagaStateChangeCausedByMessage(IInvokeHandlerContext context, SagaUpdatedMessage sagaAudit)
    {
        if (!context.Headers.TryGetValue("NServiceBus.Serilog.SagaStateChange", out var sagaStateChange))
        {
            sagaStateChange = string.Empty;
        }

        var stateChange = "Updated";

        if (sagaAudit.IsNew)
        {
            stateChange = "New";
        }

        if (sagaAudit.IsCompleted)
        {
            stateChange = "Completed";
        }

        if (!string.IsNullOrEmpty(sagaStateChange))
        {
            sagaStateChange += ";";
        }

        sagaStateChange += $"{sagaAudit.SagaId}:{stateChange}";

        context.Headers["NServiceBus.Serilog.SagaStateChange"] = sagaStateChange;
    }
コード例 #4
0
        public static SagaSnapshot Create(SagaUpdatedMessage message)
        {
            var sagaSnapshot = new SagaSnapshot
            {
                SagaId = message.SagaId,
                SagaType = message.SagaType,
                FinishTime = message.FinishTime,
                StartTime = message.StartTime,
                StateAfterChange = message.SagaState,
                Endpoint = message.Endpoint,
                InitiatingMessage = CreateInitiatingMessage(message.Initiator)
            };

            if (message.IsNew)
            {
                sagaSnapshot.Status = SagaStateChangeStatus.New;
            }
            else
            {
                sagaSnapshot.Status = SagaStateChangeStatus.Updated;
            }

            if (message.IsCompleted)
            {
                sagaSnapshot.Status = SagaStateChangeStatus.Completed;
            }

            sagaSnapshot.ProcessedAt = message.FinishTime;

            AddResultingMessages(message.ResultingMessages, sagaSnapshot);
            return sagaSnapshot;
        }
コード例 #5
0
        public override async Task Invoke(IInvokeHandlerContext context, Func <Task> next)
        {
            var sagaAudit = new SagaUpdatedMessage();

            context.Extensions.Set(sagaAudit);

            await next().ConfigureAwait(false);

            if (!context.Extensions.TryGet(out ActiveSagaInstance activeSagaInstance))
            {
                return; // Message was not handled by the saga
            }

            if (activeSagaInstance.Instance.Entity == null)
            {
                return; // Message was not handled by the saga
            }

            await AuditSaga(activeSagaInstance, sagaAudit, context).ConfigureAwait(false);
        }
コード例 #6
0
        public void SagaUpdated_serializes_correctly()
        {
            var entity = new SagaUpdatedMessage
            {
                SagaId     = Guid.Empty,
                SagaState  = "SagaState",
                Endpoint   = "Endpoint",
                FinishTime = new DateTime(2017, 10, 30, 9, 22, 17, DateTimeKind.Utc),
                Initiator  = new SagaChangeInitiator
                {
                    InitiatingMessageId = "InitiatingMessageId",
                    Intent = "intent",
                    IsSagaTimeoutMessage = true,
                    MessageType          = "MessageType",
                    OriginatingEndpoint  = "OriginatingEndpoint",
                    OriginatingMachine   = "OriginatingMachine",
                    TimeSent             = new DateTime(2017, 10, 30, 9, 22, 17, DateTimeKind.Utc)
                },
                IsCompleted       = true,
                IsNew             = true,
                ResultingMessages =
                {
                    new SagaChangeOutput
                    {
                        Destination        = "Destination",
                        MessageType        = "MessageType",
                        DeliveryAt         = new DateTime(2017, 10, 30, 9, 22, 17, DateTimeKind.Utc),
                        DeliveryDelay      = TimeSpan.FromSeconds(4000),
                        Intent             = "Intent",
                        ResultingMessageId = "ResultingMessageId",
                        TimeSent           = new DateTime(2017, 10, 30, 9, 22, 17, DateTimeKind.Utc)
                    }
                },
                SagaType  = "SagaType",
                StartTime = new DateTime(2017, 10, 30, 9, 22, 17, DateTimeKind.Utc)
            };
            var serialized = SimpleJson.SimpleJson.SerializeObject(entity, new MessageSerializationStrategy());

            Approver.Verify(serialized);
        }
コード例 #7
0
        Task AuditSaga(ActiveSagaInstance activeSagaInstance, SagaUpdatedMessage sagaAudit, IInvokeHandlerContext context)
        {
            if (!context.Headers.TryGetValue(Headers.MessageId, out var messageId))
            {
                return(Task.FromResult(0));
            }

            var saga = activeSagaInstance.Instance;

            string sagaStateString;

            if (customSagaEntitySerialization != null)
            {
                sagaStateString = SimpleJson.SerializeObject(customSagaEntitySerialization(saga.Entity));
            }
            else
            {
                sagaStateString = SimpleJson.SerializeObject(saga.Entity, sagaEntitySerializationStrategy);
            }

            var messageType = context.MessageMetadata.MessageType.FullName;
            var headers     = context.MessageHeaders;

            sagaAudit.StartTime   = activeSagaInstance.Created.UtcDateTime;
            sagaAudit.FinishTime  = activeSagaInstance.Modified.UtcDateTime;
            sagaAudit.Initiator   = BuildSagaChangeInitiatorMessage(headers, messageId, messageType);
            sagaAudit.IsNew       = activeSagaInstance.IsNew;
            sagaAudit.IsCompleted = saga.Completed;
            sagaAudit.Endpoint    = endpointName;
            sagaAudit.SagaId      = saga.Entity.Id;
            sagaAudit.SagaType    = saga.GetType().FullName;
            sagaAudit.SagaState   = sagaStateString;

            AssignSagaStateChangeCausedByMessage(context, activeSagaInstance, sagaAudit);

            var transportTransaction = context.Extensions.Get <TransportTransaction>();

            return(backend.Send(sagaAudit, transportTransaction, context.CancellationToken));
        }
コード例 #8
0
 public Task Send(SagaUpdatedMessage messageToSend, TransportTransaction transportTransaction, CancellationToken cancellationToken = default)
 {
     return(Send(messageToSend, TimeSpan.MaxValue, transportTransaction, cancellationToken));
 }
コード例 #9
0
        static void AssignSagaStateChangeCausedByMessage(IInvokeHandlerContext context, ActiveSagaInstance sagaInstance, SagaUpdatedMessage sagaAudit)
        {
            if (!context.MessageHeaders.TryGetValue(SagaAuditHeaders.SagaStateChange, out var sagaStateChange))
            {
                sagaStateChange = string.Empty;
            }

            var statechange = "Updated";

            if (sagaInstance.IsNew)
            {
                statechange = "New";
            }
            if (sagaInstance.Instance.Completed)
            {
                statechange = "Completed";
            }

            if (!string.IsNullOrEmpty(sagaStateChange))
            {
                sagaStateChange += ";";
            }
            sagaStateChange += $"{sagaAudit.SagaId}:{statechange}";

            context.Headers[SagaAuditHeaders.SagaStateChange] = sagaStateChange;
        }
    public override async Task Invoke(IInvokeHandlerContext context, Func <Task> next)
    {
        if (context.MessageHandler.Instance is not Saga)
        {
            // Message was not handled by the saga
            await next();

            return;
        }

        var logger = context.Logger();

        if (!logger.IsEnabled(LogEventLevel.Information))
        {
            await next();

            return;
        }

        var sagaAudit = new SagaUpdatedMessage();

        context.Extensions.Set(sagaAudit);
        var startTime = DateTimeOffset.UtcNow;

        await next();

        var finishTime = DateTimeOffset.UtcNow;

        if (!context.Extensions.TryGet(out ActiveSagaInstance activeSagaInstance))
        {
            return;
        }

        var saga = activeSagaInstance.Instance;

        if (saga.Entity is null)
        {
            //this can happen if it is a timeout or for invoking "saga not found" logic
            return;
        }

        var headers = context.Headers;

        if (!headers.TryGetValue(Headers.MessageId, out var messageId))
        {
            return;
        }

        var isNew       = activeSagaInstance.IsNew;
        var isCompleted = saga.Completed;
        var sagaId      = saga.Entity.Id;

        AssignSagaStateChangeCausedByMessage(context, isNew, isCompleted, sagaId);

        var properties = new List <LogEventProperty>
        {
            new("SagaType", new ScalarValue(saga.GetType().Name)),
            new("SagaId", new ScalarValue(sagaId)),
            new("StartTime", new ScalarValue(startTime)),
            new("FinishTime", new ScalarValue(finishTime)),
            new("IsCompleted", new ScalarValue(isCompleted)),
            new("IsNew", new ScalarValue(isNew))
        };

        AddInitiator(context, messageId, properties);

        AddResultingMessages(sagaAudit, logger, properties);

        AddEntity(logger, saga, properties);

        logger.WriteInfo(messageTemplate, properties);
    }
    void AuditSaga(ActiveSagaInstance activeSagaInstance, IInvokeHandlerContext context, SagaUpdatedMessage sagaAudit)
    {
        var saga = activeSagaInstance.Instance;

        if (saga.Entity == null)
        {
            //this can happen if it is a timeout or for invoking "saga not found" logic
            return;
        }

        var headers = context.Headers;

        if (!headers.TryGetValue(Headers.MessageId, out var messageId))
        {
            return;
        }

        var intent = context.MessageIntent();

        var initiator = new SagaChangeInitiator
                        (
            isSagaTimeoutMessage: context.IsTimeoutMessage(),
            initiatingMessageId: messageId,
            originatingMachine: context.OriginatingMachine(),
            originatingEndpoint: context.OriginatingEndpoint(),
            messageType: context.MessageType(),
            timeSent: context.TimeSent(),
            intent: intent
                        );

        sagaAudit.IsNew       = activeSagaInstance.IsNew;
        sagaAudit.IsCompleted = saga.Completed;
        sagaAudit.SagaId      = saga.Entity.Id;

        AssignSagaStateChangeCausedByMessage(context, sagaAudit);

        var properties = new List <LogEventProperty>
        {
            new LogEventProperty("SagaType", new ScalarValue(sagaAudit.SagaType)),
            new LogEventProperty("SagaId", new ScalarValue(sagaAudit.SagaId)),
            new LogEventProperty("StartTime", new ScalarValue(sagaAudit.StartTime)),
            new LogEventProperty("FinishTime", new ScalarValue(sagaAudit.FinishTime)),
            new LogEventProperty("IsCompleted", new ScalarValue(sagaAudit.IsCompleted)),
            new LogEventProperty("IsNew", new ScalarValue(sagaAudit.IsNew)),
            new LogEventProperty("SagaType", new ScalarValue(sagaAudit.SagaType)),
        };

        var logger = context.Logger();

        if (logger.BindProperty("Initiator", initiator, out var initiatorProperty))
        {
            properties.Add(initiatorProperty);
        }

        if (logger.BindProperty("ResultingMessages", sagaAudit.ResultingMessages, out var resultingMessagesProperty))
        {
            properties.Add(resultingMessagesProperty);
        }

        if (logger.BindProperty("Entity", saga.Entity, out var sagaEntityProperty))
        {
            properties.Add(sagaEntityProperty);
        }

        logger.WriteInfo(messageTemplate, properties);
    }
コード例 #12
0
    void AuditSaga(ActiveSagaInstance activeSagaInstance, IInvokeHandlerContext context, SagaUpdatedMessage sagaAudit)
    {
        var saga = activeSagaInstance.Instance;

        if (saga.Entity == null)
        {
            //this can happen if it is a timeout or for invoking "saga not found" logic
            return;
        }

        var headers = context.Headers;

        if (!headers.TryGetValue(Headers.MessageId, out var messageId))
        {
            return;
        }

        var intent = context.MessageIntent();

        sagaAudit.IsNew       = activeSagaInstance.IsNew;
        sagaAudit.IsCompleted = saga.Completed;
        sagaAudit.SagaId      = saga.Entity.Id;

        AssignSagaStateChangeCausedByMessage(context, sagaAudit);

        List <LogEventProperty> properties = new()
        {
            new("SagaType", new ScalarValue(sagaAudit.SagaType)),
            new("SagaId", new ScalarValue(sagaAudit.SagaId)),
            new("StartTime", new ScalarValue(sagaAudit.StartTime)),
            new("FinishTime", new ScalarValue(sagaAudit.FinishTime)),
            new("IsCompleted", new ScalarValue(sagaAudit.IsCompleted)),
            new("IsNew", new ScalarValue(sagaAudit.IsNew))
        };

        var logger      = context.Logger();
        var messageType = TypeNameConverter.GetName(context.MessageType());

        Dictionary <ScalarValue, LogEventPropertyValue> initiator = new()
        {
            { new("IsSagaTimeout"), new ScalarValue(context.IsTimeoutMessage()) },
            { new("MessageId"), new ScalarValue(messageId) },