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.
In
ConfigureHowToFindSaga()
you are telling the saga persister that you will be looking up the saga based on 2 unique propertiesReferenceKey
orMessageIdentifier
, depending upon the incoming message type. However, inTrackingSagaData
you are only markingReferenceKey
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:
[Unique]
properties, you probably just aren't even to that point yet due to the new() problems.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.