Last active
July 12, 2018 09:07
-
-
Save ramonsmits/75a80ec9a45f8042bc4f to your computer and use it in GitHub Desktop.
NServiceBus buffering saga example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomerNotificationHandler | |
: IHandleMessage<CustomerOrderNotification> | |
, IHandleMessage<CustomerOrderStatusNotification> | |
{ | |
public IBus Bus {get;set;} | |
INotificationService GetClientForCustomer(string customerId) | |
{ | |
return null; // Create a api client for your customer | |
} | |
public void Handle(CustomerOrderNotification message) | |
{ | |
var service = GetClientForCustomer(message.CustomerId); | |
service.Notifiy(message); | |
Bus.Reply(new Notified()); | |
} | |
public void Handle(CustomerOrderStatusNotification message) | |
{ | |
var service = GetClientForCustomer(message.CustomerId); | |
service.Notifiy(message); | |
Bus.Reply(new Notified()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on saga data for message buffer | |
public class CustomerOrderNotificationSaga<CustomerOrderNotificationSaga.Data> | |
: IAmStartedByMessages<OrderCreated> | |
, IHandleMessages<OrderStatusChanged> | |
{ | |
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<CustomerOrderNotificationSaga.Data> mapper) | |
{ | |
// Mapping for OrderCreated is not required, as it is started by it. | |
mapper.ConfigureMapping<OrderStatusChanged>(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId); | |
} | |
public void Handle(OrderCreated message) | |
{ | |
Data.OrderId = message.OrderId; | |
Bus.Send(new CustomerOrderNotification{ | |
CustomerId = message.CustomerId, | |
OrderId = message.OrderId, | |
// Other order info? | |
}); | |
} | |
public void Handle(OrderStatusChanged message) | |
{ | |
var instance = new CustomerOrderStatusNotification | |
{ | |
CustomerId = message.CustomerId, | |
OrderId = message.OrderId, | |
Status = message.Status, | |
Version = message.Version, // <-- Provides ordering! | |
}; | |
Notifications.Add(instance); | |
Next(); | |
} | |
public void Handle(Notified message) | |
{ | |
Data.OrderNr++; // <-- Increase version | |
if(Notifications.Count>0) | |
{ | |
Next(); | |
} | |
} | |
void Next() | |
{ | |
CustomerOrderStatusNotification instance = notifications | |
.OrderBy(x=>x.Version) | |
.First(); | |
if(Data.OrderNr != instance.Version) | |
{ | |
return; // Versions are not equal! | |
} | |
notifications.Remove(instance); | |
Bus.Send(instance); | |
} | |
public class Data | |
{ | |
[Unique] | |
public virtual string OrderId {get;set;} | |
public virtual ICollection<CustomerOrderStatusNotification> Notifications {get;set;} | |
public virtual int OrderNr {get;set;} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on retry logic | |
public class CustomerOrderNotificationSaga<CustomerOrderNotificationSaga.Data> | |
: IAmStartedByMessages<OrderCreated> | |
, IHandleMessages<OrderStatusChanged> | |
{ | |
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<CustomerOrderNotificationSaga.Data> mapper) | |
{ | |
// Mapping for OrderCreated is not required, as it is started by it. | |
mapper.ConfigureMapping<OrderStatusChanged>(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId); | |
} | |
public void Handle(OrderCreated message) | |
{ | |
Data.OrderId = message.OrderId; | |
Bus.Send(new CustomerOrderNotification{ | |
CustomerId = message.CustomerId, | |
OrderId = message.OrderId, | |
// Other order info? | |
}); | |
} | |
public void Handle(OrderStatusChanged message) | |
{ | |
if(Data.OrderNr == 0) | |
{ | |
throw new InvalidOperation("Version out of order, order delivery not yet confirmed."); | |
} | |
var instance = new CustomerOrderStatusNotification | |
{ | |
CustomerId = message.CustomerId, | |
OrderId = message.OrderId, | |
Status = message.Status, | |
Timestamp = message.Timestamp | |
}; | |
Bus.Send(instance); | |
} | |
public void Handle(Notified message) | |
{ | |
Data.OrderNr++; | |
} | |
public class Data : SagaData | |
{ | |
[Unique] | |
public virtual string OrderId {get;set;} | |
public virtual int OrderNr {get;set;} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on retry logic | |
public class CustomerOrderNotificationSaga<CustomerOrderNotificationSaga.Data> | |
: IAmStartedByMessages<OrderCreated> | |
, IHandleMessages<OrderStatusChanged> | |
{ | |
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<CustomerOrderNotificationSaga.Data> mapper) | |
{ | |
// Mapping for OrderCreated is not required, as it is started by it. | |
mapper.ConfigureMapping<OrderStatusChanged>(message => message.OrderId).ToSaga(sagaData => sagaData.OrderId); | |
} | |
public void Handle(OrderCreated message) | |
{ | |
Data.OrderId = message.OrderId; | |
Bus.Send(new CustomerOrderNotification{ | |
CustomerId = message.CustomerId, | |
OrderId = message.OrderId, | |
// Other order info? | |
}); | |
} | |
public void Handle(OrderStatusChanged message) | |
{ | |
if(Data.OrderNr != message.Version) | |
{ | |
throw new InvalidOperation("Version out of order."); | |
} | |
var instance = new CustomerOrderStatusNotification | |
{ | |
CustomerId = message.CustomerId, | |
OrderId = message.OrderId, | |
Status = message.Status, | |
Version = message.Version, // <-- Provides ordering! | |
}; | |
Bus.Send(instance); | |
} | |
public void Handle(Notified message) | |
{ | |
Data.OrderNr++; | |
} | |
public class Data : SagaData | |
{ | |
[Unique] | |
public virtual bool OrderId {get;set;} | |
public virtual int OrderNr {get;set;} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment