Last active
August 29, 2015 14:01
-
-
Save geersch/edd75a600e86fb59130b to your computer and use it in GitHub Desktop.
#1 - Creating a projection
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
// Compose a projection. | |
// - Tell what type of state the projection maintains (List<WizardActivity>) | |
var projection = Compose<List<WizardActivity>>.Projection() | |
.Initialize(() => new List<WizardActivity>()) // How do you want to initialize the state when you run the projection? | |
// When a wizard was started we want to know about it. | |
.When<WizardStarted>((@event, state) => | |
{ | |
var activity = new WizardActivity(@event.CorrelationId.Value, @event.TimeStamp); | |
if (!state.Contains(activity)) | |
state.Add(activity); | |
}) | |
// Register the endtime when a wizard was finished. | |
.When<WizardFinished>((@event, state) => | |
{ | |
var activity = state.SingleOrDefault(s => s.CorrelationId == @event.CorrelationId.Value); | |
if (activity != null) | |
{ | |
activity.FinishedAt = @event.TimeStamp; | |
} | |
}) | |
.Build(); |
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
// Using a projection | |
// Read 125 trace events from a file (or whereever the events are coming from) | |
var json = File.ReadAllText("traceevents.txt"); | |
var traceEvents = json.Parse<IEnumerable<TraceEvent>>(); | |
var player = new EventPlayer(new[] { projection }); | |
player.Play(traceEvents.ToArray()); | |
Console.WriteLine("{0} wizard activities composed.", projection.State.Count); |
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 static class Compose<TState> where TState : class, new() | |
{ | |
public static ProjectionBuilder<TState> Projection() | |
{ | |
return new ProjectionBuilder<TState>(); | |
} | |
} | |
public class ProjectionBuilder<TState> where TState : class, new() | |
{ | |
private TraceEventHandler<TState>[] _handlers; | |
private Func<TState> _initializer; | |
public ProjectionBuilder() | |
: this(new TraceEventHandler<TState>[0]) | |
{ | |
} | |
public ProjectionBuilder(TraceEventHandler<TState>[] handlers) | |
{ | |
Guard.That(handlers).IsNotNull(); | |
_handlers = handlers; | |
} | |
public ProjectionBuilder<TState> Initialize(Func<TState> initializer) | |
{ | |
_initializer = initializer; | |
return this; | |
} | |
public ProjectionBuilder<TState> When<TEvent>(Action<TraceEvent, TState> handler) | |
where TEvent : Event | |
{ | |
Guard.That(handler).IsNotNull(); | |
var newHandler = new TraceEventHandler<TState>(typeof(TEvent), handler); | |
_handlers = _handlers.Concat(new[] { newHandler }).ToArray(); | |
return this; | |
} | |
public Projection<TState> Build() | |
{ | |
return new Projection<TState>(_initializer, _handlers); | |
} | |
} | |
public class TraceEventHandler<TState> where TState: class, new() | |
{ | |
private readonly Type _event; | |
private readonly Action<TraceEvent, TState> _handler; | |
public TraceEventHandler(Type @event, Action<TraceEvent, TState> handler) | |
{ | |
Guard.That(@event).IsNotNull(); | |
Guard.That(handler).IsNotNull(); | |
_event = @event; | |
_handler = handler; | |
} | |
public Type Event | |
{ | |
get { return _event; } | |
} | |
public Action<TraceEvent, TState> Handler | |
{ | |
get { return _handler; } | |
} | |
} | |
public interface IProjection | |
{ | |
void Run(TraceEvent[] traceEvents); | |
} | |
public class Projection<TState> : IProjection | |
where TState : class, new() | |
{ | |
private readonly Func<TState> _initializeState; | |
private readonly TraceEventHandler<TState>[] _handlers; | |
private TState _state; | |
public Projection( | |
Func<TState> initializeState, | |
TraceEventHandler<TState>[] handlers) | |
{ | |
Guard.That(initializeState).IsNotNull(); | |
Guard.That(handlers).IsNotNull(); | |
_initializeState = initializeState; | |
_handlers = handlers; | |
} | |
public IReadOnlyCollection<TraceEventHandler<TState>> Handlers | |
{ | |
get { return _handlers; } | |
} | |
public TState State | |
{ | |
get { return _state; } | |
} | |
public void Run(TraceEvent[] traceEvents) | |
{ | |
_state = _initializeState(); | |
foreach (var traceEvent in traceEvents) | |
{ | |
foreach (var handler in Handlers) | |
{ | |
if (handler.Event.Name != traceEvent.EventType) | |
continue; | |
var handleIt = handler.Handler; | |
handleIt(traceEvent, _state); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment