Prerequisites
Ensure an instance of MongoDB is executing on localhost:27017
.
The easiest way to do this is to run MongoDB in Docker by running the following commands
docker run -d -p 27017:27017 --name TestMongoDB mongo:latest --replSet tr0
docker exec -it TestMongoDB mongosh --eval 'rs.initiate()'
Alternatively, it is possible to install MongoDB but the instance must be part of a replica set to enable transactions. If this is not possible, the endpoint configuration must be altered to disable transactions (not recommended for production):
endpointConfiguration.UsePersistence<MongoPersistence>().UseTransactions(false)
Data visualization
To visualize data in MongoDB, it is useful to install a MongoDB visualization tool. The screen shots in this sample are from Robomongo.
Code walk-through
This sample shows a simple client/server scenario:
Client
sends aStartOrder
message toServer
Server
starts anOrderSaga
instanceOrderSaga
requests a timeout withCompleteOrder
dataCompleteOrder
timeout occurs andOrderSaga
publishes anOrderCompleted
eventOrderCompleted
is delivered toClient
, becauseClient
is subscribed to that eventClient
handlesOrderCompleted
MongoDB configuration
The Server
endpoint is configured to use MongoDB persistence.
var endpointConfiguration = new EndpointConfiguration("Samples.MongoDB.Server");
var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
persistence.DatabaseName("Samples_MongoDB_Server");
- If a MongoDB URL is not specified, the persistence uses the default of
mongodb:/
./ localhost:27017 - If a database name is not specified, the persistence uses the endpoint name as the database name. In this sample the database name is
Samples_MongoDB_Server
.
Order saga
public class OrderSaga :
Saga<OrderSagaData>,
IAmStartedByMessages<StartOrder>,
IHandleTimeouts<CompleteOrder>
{
static ILog log = LogManager.GetLogger<OrderSaga>();
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<OrderSagaData> mapper)
{
mapper.MapSaga(sagaData => sagaData.OrderId)
.ToMessage<StartOrder>(message => message.OrderId);
}
public Task Handle(StartOrder message, IMessageHandlerContext context)
{
Data.OrderId = message.OrderId;
var orderDescription = $"The saga for order {message.OrderId}";
Data.OrderDescription = orderDescription;
log.Info($"Received StartOrder message {Data.OrderId}. Starting Saga");
log.Info("Order will complete in 5 seconds");
var timeoutData = new CompleteOrder
{
OrderDescription = orderDescription
};
return RequestTimeout(context, TimeSpan.FromSeconds(5), timeoutData);
}
public Task Timeout(CompleteOrder state, IMessageHandlerContext context)
{
log.Info($"Saga with OrderId {Data.OrderId} completed");
var orderCompleted = new OrderCompleted
{
OrderId = Data.OrderId
};
MarkAsComplete();
return context.Publish(orderCompleted);
}
}
Saga data
The saga data is stored in the ordersagadata
collection.
public class OrderSagaData : ContainSagaData
{
public Guid OrderId { get; set; }
public string OrderDescription { get; set; }
}
_id
storesIContainSagaData.
Id _t
is type serialization metadata used by the MongoDB .NET/C# DriverOriginator
storesIContainSagaData.
Originator OriginalMessageId
storesIContainSagaData.
OriginalMessageId OrderID
storesOrderSagaData.
OrderID OrderDescription
storesOrderSagaData.
OrderDescription _version
is added and managed by the persistence to prevent concurrency issues