NServiceBus : Document '<SagaName>' no longer exists and was probably deleted

224 Views Asked by At

I'm trying to : Get message from an endpoint. The message will contain serialized MessageClass. I want to start a new saga only if MessageClass.MessageIdentifier is unique.

My Saga looks like this :

public class TrackingSaga:Saga<TrackingSagaData>,IAmStartedByMessages<InsertMessgae>,IHandleMessages<DeleteMessage>
{
    private IBusinessService _trackingBusinessService;
    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<DeleteMessage>(s => s.ReferenceKey, p => p.ReferenceKey);
        ConfigureMapping<InsertMessage>(s=>s.MessageIdentifier,p=>p.MessageIdentifier);
    }
}

public void Handle(InsertMessage message)
{
 Data=new TrackingSagaData(message.MessageClass)
          {
            MessageIdentifier = message.MessageClass.MessageIdentifier;
          }

 var trackingBusinessService = <<spring will provide me>> ;
 trackingBusinessService.RecordNewMessage(message.MessageClass);
}

Here is the Saga data :

 public class TrackingSagaData : ParentSagaData
{

    public MessageClass MessageClass { private set; get; }
    [Unique]
    public Guid ReferenceKey { get { return MessageClass.ReferenceKey; } }
    public string MessageIdentifier { get { return MessageClass.MessageIdentifier; } }
    public bool IsMessageDeleted { set; get; }

    public TrackingSagaData()
    {

    }
    public TrackingSagaData(MessageClass messageClass)
    {
        MessageClass= messageClass;
        IsMessageDeleted = false;
    }

Here is the bus configuration :

Configure.With()
                 .Log4Net()
                 .DefaultBuilder()
                 .XmlSerializer()
                 .RavenSubscriptionStorage()
                 .MsmqTransport()
                 .IsTransactional(true)
                 .PurgeOnStartup(false)
                 .RavenPersistence()
                 .UnicastBus();

When I run my endpoint, the console displays the warning:

2014-06-27 18:17:10,040 [Worker.14] WARN  NServiceBus.Unicast.UnicastBus [(null)
] <(null)> - IncidentTrackingSaga failed handling message.
System.InvalidOperationException: Document 'trackingsagadata/1fcfd00d-6b97-4
dc2-aa09-18a1bd0631e2' no longer exists and was probably deleted

2014-06-27 18:17:10,070 [Worker.14] WARN  NServiceBus.Unicast.Transport.Transact
ional.TransactionalTransport [(null)] - Failed raising 'transport message receiv
ed' event for message with ID=88d86af8-5925-4975-ac72-7e68885070ab\18218
NServiceBus.Unicast.Transport.TransportMessageHandlingFailedException: Exception
of type 'NServiceBus.Unicast.Transport.TransportMessageHandlingFailedException'
was thrown.

However, if I remove the statements :

ConfigureMapping<InsertMessage>(s=>s.MessageIdentifier,p=>p.MessageIdentifier);

and

MessageIdentifier = message.MessageClass.MessageIdentifier;

then the whole application runs fine but new Saga is getting created for the same Message. I know this because RecordNewMessage() will write in DB and I see multiple insertions for the same MessageClass.MessageIdentifier.

1

There are 1 best solutions below

3
On

In ConfigureHowToFindSaga() you are telling the saga persister that you will be looking up the saga based on 2 unique properties ReferenceKey or MessageIdentifier, depending upon the incoming message type. However, in TrackingSagaData you are only marking ReferenceKey as [Unique].

This is a problem because, in RavenDB only Load/Store by ID is an ACID operation. The Raven Saga Persister uses identity documents based on the [Unique] attributes, which you aren't providing.

Now the bigger problem is, I don't think you can have two [Unique] properties for the same saga data. Is there a way you can redesign the saga so that both messages will carry the same unique property? (Or rather, the same value of the same type - the property names on the messages need not be identical.)

You mentioned in the comments you were doing Data = new TrackingSaga() and you are correct, you should not be doing that! NServiceBus will create that class for you, along with 3 properties that NServiceBus needs to control the lifecycle of the Saga. If you new it up yourself, you blow away those properties and nothing can work.

So, you should only modify properties on the Saga, not new() it up yourself.

To be a bit more clear on other points:

  • You are still going to have a problem with the [Unique] properties, you probably just aren't even to that point yet due to the new() problems.
  • ConfigureMapping() will not throw errors. Your mappings just won't work right on a failure. You'll get a new saga created when an old one should have been found, or a message will be ignored because it "couldn't find" the original saga data.

My recommendation still stands to redesign the saga to use one common identifying property found in all message types, or do as Sean suggested and create your own saga finder, although this requires pretty intimate understanding of how RavenDB works as you'd essentially be communicating directly with the database.