public class CustomerRevenueNode : Node, Node.IHandle, Node.IHandle, Node.IHandle { public class State { public Guid CustomerId { get; set; } public decimal AggregatedRevenue { get; set; } public IDictionary PendingOrderAmounts { get; } = new Dictionary(); } private readonly ICustomerRevenueStore _store; public CustomerRevenueNode(ICustomerRevenueStore store) { _store = store; } public async Task AccessMemory(OrderPlaced orderPlaced) { var snapshot = await _store.GetByCustomerId(orderPlaced.CustomerId).ConfigureAwait(false); return new Memory(snapshot, nextState => _store.Save(nextState)); } public async Task AccessMemory(OrderCancelled orderCancelled) { var snapshot = await _store.GetByOrderId(orderCancelled.OrderId).ConfigureAwait(false); return new Memory(snapshot, nextState => _store.Save(nextState)); } public async Task AccessMemory(OrderDelivered orderDelivered) { var snapshot = await _store.GetByOrderId(orderDelivered.OrderId).ConfigureAwait(false); return new Memory(snapshot, nextState => _store.Save(nextState)); } public ITransformResult Transform(OrderPlaced orderPlaced, CustomerRevenueNode.State state) { var nextState = state ?? new CustomerRevenueNode.State { CustomerId = orderPlaced.CustomerId }; nextState.PendingOrderAmounts.Add(orderPlaced.Id, orderPlaced.Amount); return new Node.TransformResult(nextState); } public ITransformResult Transform(OrderCancelled orderCancelled, CustomerRevenueNode.State state) { var nextState = state; nextState.PendingOrderAmounts.Remove(orderCancelled.OrderId); return new Node.TransformResult(nextState); } public ITransformResult Transform(OrderDelivered orderDelivered, CustomerRevenueNode.State state) { var nextState = state; nextState.AggregatedRevenue += nextState.PendingOrderAmounts[orderDelivered.OrderId]; nextState.PendingOrderAmounts.Remove(orderDelivered.OrderId); return new Node.TransformResult(nextState); } } public interface ICustomerRevenueStore { Task GetByCustomerId(Guid customerId); Task GetByOrderId(Guid orderId); Task Save(CustomerRevenueNode.State state); }