public void DispatchingEventsInTheWrongOrderWithANonZeroStartingSequenceNumber( IRepository <string, SomeData> repository, View view, ISequenceResolver sequenceResolver, IViewManager viewManager, SomeEvent firstEvent, SomeEvent secondEvent) { "Given a view repository"._(() => repository = new MemoryRepository <string, SomeData>()); "and a view"._(() => view = new SomeView(repository)); "and a sequence resolver"._(() => sequenceResolver = new CustomSequenceResolver()); "and a view manager"._(ctx => viewManager = ViewManager.ForViews(view).OrderEventsUsing(sequenceResolver).StartAtSequenceNumber(2).Create().Using(ctx)); "and a first event"._(() => firstEvent = new SomeEvent { Sequence = 2, Id = "test2" }); "and a second event"._(() => secondEvent = new SomeEvent { Sequence = 3, Id = "test3" }); "when those events are dispatched out of order"._( () => { viewManager.QueueForDispatch(secondEvent); viewManager.QueueForDispatch(firstEvent); }); "and the operation is given time to process"._(() => Thread.Sleep(1000)); "then the view received the second event last"._(() => repository.Get("root").LastEventId.Should().Be(secondEvent.Id)); "and the view received two events"._(() => repository.Get("root").EventCount.Should().Be(1)); }
public void EventReplayingOnStartUp( List <SomeEvent> eventStore, IRepository <string, SomeData> repository, View view, ISequenceResolver sequenceResolver, IEventResolver eventResolver, IViewManager viewManager) { "Given an event store with three events"._(() => eventStore = new List <SomeEvent> { new SomeEvent { Sequence = 1, Id = "test" }, new SomeEvent { Sequence = 2, Id = "test2" }, new SomeEvent { Sequence = 3, Id = "test3" }, }); "and a view repository"._(() => repository = new MemoryRepository <string, SomeData>()); "and a view"._(() => view = new SomeView(repository)); "and a sequence resolver"._(() => sequenceResolver = new CustomSequenceResolver()); "and an event resolver"._(() => eventResolver = new CustomEventResolver(eventStore)); "when a view manager is created"._(ctx => viewManager = ViewManager.ForViews(view) .OrderEventsUsing(sequenceResolver).StartAtSequenceNumber(0) .ResolveMissingEventsUsing(eventResolver).WithATimeoutOf(Timeout.Infinite) .Create().Using(ctx)); "and the operation is given time to process"._(() => Thread.Sleep(1000)); "then the view received the third event last"._(() => repository.Get("root").LastEventId.Should().Be(eventStore[2].Id)); "and the view received three events"._(() => repository.Get("root").EventCount.Should().Be(3)); }
public void SubsequentViewPersistence( IRepository <string, SomeData> repository, View view, ISequenceResolver sequenceResolver, IRepository <string, Snapshot> snapshotRepository, IViewManager viewManager, SomeEvent firstEvent, SomeEvent secondEvent, SomeData initialData, SomeData actualInitialData, SomeData subsequentData) { "Given a view repository"._(() => repository = new MemoryRepository <string, SomeData>()); "and some intial data"._( () => initialData = new SomeData { LastEventId = "test2", EventCount = 2, }); "and the repository contains the initial data"._(() => repository.AddOrUpdate("root", initialData)); "and a view"._(() => view = new SomeView(repository)); "and a sequence resolver"._(() => sequenceResolver = new CustomSequenceResolver()); "and a snapshot repository"._(() => snapshotRepository = new MemoryRepository <string, Snapshot>()); "and the snapshot repository contains the initial snapshot data"._( () => snapshotRepository.AddOrUpdate( view.GetType().FullName, new Snapshot { ViewName = view.GetType().FullName, PersistedSequenceNumber = 2, })); "and a view manager"._(ctx => viewManager = ViewManager.ForViews(view) .OrderEventsUsing(sequenceResolver) .SnapshotViewsUsing(snapshotRepository).WithAQuietTimeTimeoutOf(2) .Create().Using(ctx)); "and a third event"._(() => firstEvent = new SomeEvent { Sequence = 3, Id = "test3" }); "and a fourth event"._(() => secondEvent = new SomeEvent { Sequence = 4, Id = "test4" }); "when those events are dispatched"._( () => { viewManager.QueueForDispatch(firstEvent); viewManager.QueueForDispatch(secondEvent); }); "and the operation is given time to process"._(() => Thread.Sleep(1000)); "and the repository is queried initially"._(() => actualInitialData = repository.Get("root")); "and the snapshot is given time to process"._(() => Thread.Sleep(2000)); "and the repository is queried subsequently"._(() => subsequentData = repository.Get("root")); "then the initial query should be empty"._(() => actualInitialData.Should().Be(initialData)); "and the view received the second event last"._(() => subsequentData.LastEventId.Should().Be(secondEvent.Id)); "and the view received two events"._(() => subsequentData.EventCount.Should().Be(4)); }
public void Execute_TypeWithoutParam_CorrectEvaluation() { var args = new CustomSequenceResolverArgs ( new LiteralScalarResolver <string>(GetType().Assembly.Location), new LiteralScalarResolver <string>($"{typeof(MyCustomClass).Namespace}.{typeof(MyCustomClass).Name}"), new Dictionary <string, IScalarResolver>() ); var resolver = new CustomSequenceResolver <string>(args); Assert.That(resolver.Execute(), Has.Member("myFirstValue")); Assert.That(resolver.Execute(), Has.Member("mySecondValue")); Assert.That(resolver.Execute(), Has.Member("myThirdValue")); }
public void Execute_TypeWithParam_CorrectEvaluation() { var args = new CustomSequenceResolverArgs ( new LiteralScalarResolver <string>(GetType().Assembly.Location), new LiteralScalarResolver <string>($"{typeof(MyCustomClassWithParams).Namespace}.{typeof(MyCustomClassWithParams).Name}"), new Dictionary <string, IScalarResolver>() { { "foo", new LiteralScalarResolver <int>(5) }, { "bar", new LiteralScalarResolver <DateTime>(new DateTime(2019, 1, 1)) } } ); var resolver = new CustomSequenceResolver <DateTime>(args); var output = resolver.Execute(); Assert.That(output, Has.Member(new DateTime(2019, 1, 6))); Assert.That(output, Has.Member(new DateTime(2018, 12, 27))); }
public void InitialViewPersistence( IRepository <string, SomeData> repository, View view, ISequenceResolver sequenceResolver, IRepository <string, Snapshot> snapshotRepository, IViewManager viewManager, SomeEvent firstEvent, SomeEvent secondEvent, SomeData initialData, SomeData subsequentData) { "Given a view repository"._(() => repository = new MemoryRepository <string, SomeData>()); "and a view"._(() => view = new SomeView(repository)); "and a sequence resolver"._(() => sequenceResolver = new CustomSequenceResolver()); "and a snapshot repository"._(() => snapshotRepository = new MemoryRepository <string, Snapshot>()); "and a view manager"._(ctx => viewManager = ViewManager.ForViews(view) .OrderEventsUsing(sequenceResolver) .SnapshotViewsUsing(snapshotRepository).WithAQuietTimeTimeoutOf(2) .Create().Using(ctx)); "and a first event"._(() => firstEvent = new SomeEvent { Sequence = 1, Id = "test" }); "and a second event"._(() => secondEvent = new SomeEvent { Sequence = 2, Id = "test2" }); "when those events are dispatched"._( () => { viewManager.QueueForDispatch(firstEvent); viewManager.QueueForDispatch(secondEvent); }); "and the operation is given time to process"._(() => Thread.Sleep(1000)); "and the repository is queried initially"._(() => initialData = repository.Get("root")); "and the snapshot is given time to process"._(() => Thread.Sleep(2000)); "and the repository is queried subsequently"._(() => subsequentData = repository.Get("root")); "then the initial query should be empty"._(() => initialData.Should().BeNull()); "and the view received the second event last"._(() => subsequentData.LastEventId.Should().Be(secondEvent.Id)); "and the view received two events"._(() => subsequentData.EventCount.Should().Be(2)); }
public static void Main(string[] args) { var repository1 = new MemoryRepository <long, Data.Thing>(); var repository1h = new HybridRepository <long, Data.Thing>(repository1); var repository2 = new MemoryRepository <long, Data.Thing>(); var repository3 = new MemoryRepository <string, Data.Things>(); var view1 = new Views.Thing(repository1h); var view2 = new Views.Things(repository2, repository3); var events = new List <object> { { new Events.ThingCreated { Checkpoint = 1, Id = 1, Name = "A" } }, { new Events.ThingCreated { Checkpoint = 2, Id = 2, Name = "B" } }, { new Events.ThingCreated { Checkpoint = 3, Id = 3, Name = "C" } }, { new Events.ThingUpdated { Checkpoint = 5, Id = 1, Name = "A_changed" } }, { new Events.ThingUpdated { Checkpoint = 4, Id = 1, Name = "A_changed_mistake" } }, { new Events.ThingDeleted { Checkpoint = 6, Id = 2 } }, }; var sequenceResolver = new CustomSequenceResolver(); var snapshotRepository = new MemoryRepository <string, SequenceInfo>(); #region WireUp //var x = EventDispatcher // .ForViews(view1, view2) // .Create(); //var y = EventDispatcher // .ForViews(view1, view2) // .SequenceEventsUsing(sequenceResolver) // .StartAtSequenceNumber(0) // .Create(); //var z = EventDispatcher // .ForViews(view1, view2) // .SequenceEventsUsing(sequenceResolver) // .StartAtSequenceNumber(1) // .ResolveMissingEventsUsing(null) // .WithAPublisherTimeoutOf(500) // .AndAConsumerTimeoutOf(500) // .Create(); //var a = EventDispatcher // .ForViews(view1, view2) // .SequenceEventsUsing(sequenceResolver) // .SnapshotViewsUsing(snapshotRepository) // .ResolveMissingEventsUsing(n => events.SingleOrDefault(e => sequenceResolver.GetSequenceNumber(e) == n)) // .WithAPublisherTimeoutOf(500) // .AndAConsumerTimeoutOf(500) // .Create(); var b = EventDispatcher .ForViews(view1, view2) .SequenceEventsUsing(sequenceResolver) .SnapshotViewsUsing(snapshotRepository) .Create(); var eventDispatcher = b; // defaultEventDispatcher; #endregion foreach (var @event in events.Where(e => !new long[] { 2, 6 }.Contains(sequenceResolver.GetSequenceNumber(e)))) { eventDispatcher.Dispatch(@event); } Console.ReadLine(); //orderedEventDispatcher.Dispose(); }
public static void Main(string[] args) { var repository1 = new MemoryRepository <long, Data.Thing>(); var repository1h = new HybridRepository <long, Data.Thing>(repository1); var repository2 = new MemoryRepository <long, Data.Thing>(); var repository3 = new MemoryRepository <string, Data.Things>(); var view1 = new Views.Thing(repository1h); var view2 = new Views.Things(repository2, repository3); var events = new List <object> { { new Events.ThingCreated { Checkpoint = 1, Id = 1, Name = "A" } }, { new Events.ThingCreated { Checkpoint = 2, Id = 2, Name = "B" } }, { new Events.ThingCreated { Checkpoint = 3, Id = 3, Name = "C" } }, { new Events.ThingUpdated { Checkpoint = 5, Id = 1, Name = "A_changed" } }, { new Events.ThingUpdated { Checkpoint = 4, Id = 1, Name = "A_changed_mistake" } }, { new Events.ThingDeleted { Checkpoint = 6, Id = 2 } }, }; var sequenceResolver = new CustomSequenceResolver(); var snapshotRepository = new MemoryRepository <string, Snapshot>(); #region WireUp var x = ViewManager .ForViews(view1, view2) .Create(); var y = ViewManager .ForViews(view1, view2) .OrderEventsUsing(sequenceResolver).StartAtSequenceNumber(0) .Create(); var z = ViewManager .ForViews(view1, view2) .OrderEventsUsing(sequenceResolver).StartAtSequenceNumber(1) .ResolveMissingEventsUsing((IEventResolver)null).WithATimeoutOf(Timeout.Infinite) .Create(); var b = ViewManager .ForViews(view1, view2) .OrderEventsUsing(sequenceResolver) .SnapshotViewsUsing(snapshotRepository).WithAQuietTimeTimeoutOf(Timeout.Infinite) .Create(); var a = ViewManager .ForViews(view1, view2) .OrderEventsUsing(sequenceResolver) .ResolveMissingEventsUsing(n => events.Where(e => sequenceResolver.GetSequenceNumber(e) >= n).OrderBy(o => o)).WithATimeoutOf(Timeout.Infinite) .SnapshotViewsUsing(snapshotRepository).WithAQuietTimeTimeoutOf(Timeout.Infinite) .Create(); //// should not be allowed //var c = ViewManager // .ForViews(view1, view2) // .OrderEventsUsing(sequenceResolver) // .Create(); //var d = ViewManager // .ForViews(view1, view2) // .OrderEventsUsing(sequenceResolver) // .ResolveMissingEventsUsing(n => events.SingleOrDefault(e => sequenceResolver.GetSequenceNumber(e) == n)).WithATimeoutOf(Timeout.Infinite) // .Create(); var eventDispatcher = b; // defaultEventDispatcher; #endregion foreach (var @event in events.Where(e => !new long[] { 2, 6 }.Contains(sequenceResolver.GetSequenceNumber(e)))) { eventDispatcher.QueueForDispatch(@event); } Console.ReadLine(); //orderedEventDispatcher.Dispose(); }