Created
February 3, 2016 16:49
-
-
Save nbarnwell/fadee72c0753ea1f49dc to your computer and use it in GitHub Desktop.
This file contains hidden or 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 interface Event | |
{ | |
public Guid Id; | |
public Guid CausationId; | |
public CorrelationId; | |
public Guid [AggregateName]Id; | |
public int Version; | |
} | |
public abstract class AggregateRoot | |
{ | |
private readonly IList<Event> _events = ...; | |
public Guid Id { get; private set; } | |
private void Record(Event evt) | |
{ | |
_events.Add(evt); | |
} | |
public IEnumerable<Event> GetEvents() | |
{ | |
return _events; | |
} | |
} | |
public class SalesOrder : AggregateRoot | |
{ | |
public void Create(Guid id, string reference) | |
{ | |
Record(new OrderCreated(id, reference)); | |
} | |
private void Apply(OrderCreated evt) | |
{ | |
Id = id; | |
} | |
public void PlaceOrder() | |
{ | |
if (_cancelled) | |
{ | |
throw new DomainException("Can't cancel an order that's alredy been placed."); | |
} | |
Record(new OrderPlaced(Id)); | |
} | |
public void CancelOrder() | |
{ | |
Record(new OrderCancelled(Id)); | |
} | |
private void Apply(OrderCancelled evt) | |
{ | |
_cancelled = true; | |
} | |
} | |
public class CreateOrderHandler | |
: ICommandHandler<CreateOrder> | |
{ | |
public void Handle(CreateOrder command) | |
{ | |
var o = new SalesOrder(); | |
o.Create(Guid.NewId(), command.Reference); | |
var events = o.GetEvents(); | |
_repo.Save(o); | |
_bus.Publish(events); | |
} | |
} | |
public interface IRepository<T> | |
{ | |
void Add(T item); | |
T Get(Guid id); | |
} | |
public class Repository<T> : IRepo<T> | |
{ | |
public void Add(T item) | |
{ | |
_eventStore.Save(item.Id, item.GetEvents()); | |
item.AcceptEvents(); | |
} | |
public T Get(Guid id) | |
{ | |
var events = _eventStore.Load(id); | |
var item = new T(); | |
foreach (var e in events) | |
{ | |
item.Apply(e); | |
} | |
return item; | |
} | |
} | |
public class OrderCreatedHandler | |
: IEventHandler<OrderCreated> | |
{ | |
public void Handle(OrderCreated evt) | |
{ | |
GetConnection().Execute( | |
@"insert into SalesOrder | |
(Id, Version) values (@Id, @Version);", | |
evt); | |
} | |
} | |
public class OrderCancelledHandler | |
: IEH<OrderCancelled> | |
{ | |
public void Handle(OP evt) | |
{ | |
var rowsUpdated = GetConnection.Execute( | |
@"update SalesOrder | |
set | |
Cancelled = 1, | |
Version = @Version | |
where | |
Id = @Id | |
and Version = @Version;", | |
evt); | |
if (rowsUpdated != 1) | |
{ | |
var version = c.ExecScalar("select version from so where Id = @Id"); | |
if (version >= evt.Version) | |
{ | |
return; | |
} | |
_bus.SendToBackOfQueue(evt); | |
// OR | |
_delayService.Hold(evt, TimeSpan.FromSeconds(10)); | |
// OR | |
var missing = | |
_eventStore.GetEventsSince( | |
evt.AggregateId, | |
version); | |
foreach (var missingEvent in missing) | |
{ | |
_bus.SendToSelf(missingEvent); | |
} | |
_bus.SendToSelf(evt); | |
} | |
} | |
} | |
public class OrderPlacedHandler | |
: IEH<OrderPlaced> | |
{ | |
public void Handle(OP evt) | |
{ | |
GetConnection.Execute( | |
@"update SalesOrder | |
set Placed = 1 | |
Version = @Version | |
where Id = @Id;", | |
evt); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment