Saga Not Writing to DB

Hi,

I have a saga which appears to be working ok. The database table is created and the IAmStartedByMessages handler runs when a message is put on the queue. Outbox persistence is working fine and I can see records in there, but nothing in the saga table.

Should I be seeing data written to the saga table as soon as the saga is started?

If there should be data there, what are the possible reasons that it’s not writing anything?

Thanks for your help

Rob

Should I be seeing data written to the saga table as soon as the saga is started?

The saga instance is written to storage once the message handling pipeline completes unless you immediately completes the saga.

Can you share the saga code and what persister you are using? Also what transaction mode are you running your endpoint in? (Transport Transactions • NServiceBus • Particular Docs)

Cheers,

Andreas

Hi Andreas,

I’m not setting transaction mode and using SQL Server so I assume it’s Transaction Scope.

Here is my Saga code so far:

public class OrderSaga :
    Saga<OrderSagaData>,
    IAmStartedByMessages<SubmitOrderIntegrationCommand>,
    IHandleMessages<OrderProcessedIntegrationEvent>,
    IHandleMessages<OrderSentIntegrationEvent>,
    IHandleMessages<DeliveryCreatedIntegrationEvent>,
    IHandleMessages<OrderConfirmedIntegrationEvent>,
    IHandleMessages<OrderCompletedIntegrationEvent>,
    IHandleTimeouts<CancelOrderIntegrationCommand>
{
    private const string VmrConnectorDestination = "connectors.vmr";
    private ITenantProvider _tenantProvider;

    public OrderSaga(ITenantProvider tenantProvider)
    {
        _tenantProvider = tenantProvider;
    }

    protected override void ConfigureHowToFindSaga(SagaPropertyMapper<OrderSagaData> mapper)
    {
        mapper.ConfigureMapping<SubmitOrderIntegrationCommand>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);
            
        mapper.ConfigureMapping<OrderProcessedIntegrationEvent>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);
            
        mapper.ConfigureMapping<OrderSentIntegrationEvent>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);
            
        mapper.ConfigureMapping<DeliveryCreatedIntegrationEvent>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);
        
        mapper.ConfigureMapping<OrderConfirmedIntegrationEvent>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);
                    
        mapper.ConfigureMapping<OrderCompletedIntegrationEvent>(message => message.OrderId)
            .ToSaga(sagaData => sagaData.OrderId);
    }

    public async Task Handle(SubmitOrderIntegrationCommand message, IMessageHandlerContext context)
    {
        var command = new ProcessOrderIntegrationCommand(message.OrderId);
        await context.SendLocal(command);
        
        await RequestTimeout(context, TimeSpan.FromDays(14), new CancelOrderIntegrationCommand(message.OrderId))
            .ConfigureAwait(false);
    }
    
    public async Task Handle(OrderProcessedIntegrationEvent message, IMessageHandlerContext context)
    {
        var command = new SendOrderIntegrationCommand(new OrderDto());
        var sendOptions = new SendOptions();
        sendOptions.SetDestination(VmrConnectorDestination);
        sendOptions.SetHeader("TenantId", _tenantProvider.Tenant.TenantId);
        await context.Send(command, sendOptions);
    }
    
    public async Task Handle(OrderSentIntegrationEvent message, IMessageHandlerContext context)
    {
        var command = new MarkOrderAsSentIntegrationCommand(1);
        await context.SendLocal(command);
    }
    
    public Task Handle(OrderMarkedAsSentIntegrationEvent message, IMessageHandlerContext context)
    {
        return Task.CompletedTask;
    }
    
    public async Task Handle(DeliveryCreatedIntegrationEvent message, IMessageHandlerContext context)
    {
        var command = new ConfirmOrderIntegrationCommand(1);
        await context.SendLocal(command);
    }

    public async Task Handle(OrderConfirmedIntegrationEvent message, IMessageHandlerContext context)
    {
        var command = new CompleteOrderIntegrationCommand(1);
        await context.SendLocal(command);
    }
    
    public Task Handle(OrderCompletedIntegrationEvent message, IMessageHandlerContext context)
    {
        MarkAsComplete();
        return Task.CompletedTask;
    }

    public Task Timeout(CancelOrderIntegrationCommand state, IMessageHandlerContext context)
    {
        return Task.CompletedTask;
    }
}

Thanks

Rob

The saga look ok to me, are you saying that a SubmitOrderIntegrationCommand message is processed with out errors but no saga instance is written to the DB?

Can you share the configuration code of the endpoint?

Do you have some custom behaviours registered in the pipeline?

Hi,

When you mentioned behaviours I checked to see if these were causing the issue and one of them wasn’t working properly. I’ve fixed that now and it is correctly persisting the saga.

Thanks for you assistance

Rob

Great news!

I place my bet on forgetting to call await next() ? :slight_smile: