public async Task not_run_handler_when_stream_state_has_error() { var cts = new CancellationTokenSource(); var mockAwaiter = new Mock <IHandlingManagerAwaiter>(); var mockTaskCollection = new Mock <IHandlingManagerTaskCollection>(); var mockQueue = new Mock <IHandlingQueue>(); var mockStreamStateRepo = new Mock <IStreamStateRepo>(); var mockHandlerRunner = new Mock <IHandlingManagerHandlerRunner>(); var manager = new HandlingManager(NullStandardLogger.Instance, mockAwaiter.Object, mockStreamStateRepo.Object, mockQueue.Object, mockHandlerRunner.Object, mockTaskCollection.Object); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = "x"; var queueItem = new HandlingQueueItem(parallelKey, subscriberEvent); var streamState = new StreamState(0, true); // Has error. mockQueue.Setup(x => x.IsEventsAvailable).Returns(true); mockQueue.Setup(x => x.TryDequeue(It.IsAny <IList <string> >())).Returns(queueItem); mockStreamStateRepo.Setup(x => x.LoadStreamStateAsync(It.IsAny <string>())).Callback(() => cts.Cancel()).ReturnsAsync(streamState); var timeoutToken = new CancellationTokenSource(10000).Token; await Task.WhenAny(new[] { manager.ManageAsync(cts.Token), timeoutToken.WaitHandle.AsTask() }); cts.Cancel(); if (timeoutToken.IsCancellationRequested) { throw new TimeoutException(); } mockAwaiter.Verify(x => x.ResetHandlerCompletionSignal()); mockAwaiter.VerifyNoOtherCalls(); }
public async Task enqueue_and_dequeue_items_with_correct_parallel_keys() { var cts = new CancellationTokenSource(10000); var mockQueueAwaiter = new Mock <IQueueAwaiter>(); var maxQueueSize = 2; var queue = new HandlingQueue(mockQueueAwaiter.Object, maxQueueSize); var parallelKey1 = "pk1"; var parallelKey2 = "pk2"; var subscriberEvent1 = new SubscriberEvent(null, null, 0, null, null); var subscriberEvent2 = new SubscriberEvent(null, null, 0, null, null); Assert.False(queue.IsEventsAvailable); await queue.EnqueueWithWaitAsync(parallelKey1, subscriberEvent1, cts.Token); await queue.EnqueueWithWaitAsync(parallelKey2, subscriberEvent2, cts.Token); if (cts.IsCancellationRequested) { throw new TimeoutException(); } Assert.True(queue.IsEventsAvailable); var dequeuedItem1 = queue.TryDequeue(new string[] { parallelKey2 }); var dequeuedItem2 = queue.TryDequeue(new string[] { parallelKey1 }); Assert.Equal(parallelKey1, dequeuedItem1.ParallelKey); Assert.Equal(subscriberEvent1, dequeuedItem1.SubscriberEvent); Assert.Equal(parallelKey2, dequeuedItem2.ParallelKey); Assert.Equal(subscriberEvent2, dequeuedItem2.SubscriberEvent); }
public async Task invoke_business_event_handler() { var mockSubFactory = new Mock <ISubscriberFactory>(); var businessEvent = new TestEvent(); var streamId = "s"; var position = 5; var subEvent = new SubscriberEvent(null, streamId, position, null, businessEvent); var dependencies = new ProjectorDependencies(null, mockSubFactory.Object, null, null, null, null, null); var projector = new TestProjector(dependencies); var token = CancellationToken.None; var called = false; projector.MockBusinessEventHandler = (pStreamId, pPosition, pEvent, pToken) => { Assert.Equal(streamId, pStreamId); Assert.Equal(position, pPosition); Assert.Equal(businessEvent, pEvent); Assert.Equal(token, pToken); called = true; return(Task.CompletedTask); }; await projector.HandleSubscriberEventAsync(subEvent, token); Assert.True(called); }
public async Task wait_for_enqueue_when_managing_and_no_events_in_queue() { var cts = new CancellationTokenSource(10000); var mockQueue = new Mock <ISortingQueue>(); var mockSorter = new Mock <ISubscriberEventSorter>(); var mockHandlingManager = new Mock <IHandlingManager>(); var manager = new SortingManager(NullStandardLogger.Instance, mockQueue.Object, mockSorter.Object, mockHandlingManager.Object); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = "x"; var awaitingEnqueueSignal = new ManualResetEventSlim(false); var mockEnqueueSignal = new ManualResetEventSlim(false); mockQueue.Setup(x => x.TryDequeue(out It.Ref <SubscriberEvent> .IsAny)).Returns(false); mockSorter.Setup(x => x.SortSubscriberEventToParallelKey(subscriberEvent)).Returns(parallelKey); mockQueue.Setup(x => x.AwaitEnqueueSignalAsync()).Callback(() => awaitingEnqueueSignal.Set()).Returns(mockEnqueueSignal.WaitHandle.AsTask()); var manageTask = manager.ManageAsync(cts.Token); await Task.WhenAny(new[] { awaitingEnqueueSignal.WaitHandle.AsTask(), cts.Token.WaitHandle.AsTask() }); if (cts.IsCancellationRequested) { throw new TimeoutException(); } cts.Cancel(); }
public virtual string SortSubscriberEventToParallelKey(SubscriberEvent subscriberEvent) { // Default is no parallel key, i.e. all events from the subscription stream // will be handled sequentially with no optimization to execute events in parallel. // The implementing class should override this if events can be consumed in parallel, // for example, projecting events that are from completely separate aggregate instances, // where the parallel key would be the aggregate root id, i.e. the transactional boundary. return(DEFAULT_PARALLEL_KEY); // Sorting keys may not be null or empty. }
public virtual async Task HandleSubscriberEventAsync(SubscriberEvent subscriberEvent, CancellationToken cancellationToken) { var allInterfaces = this.GetType().GetInterfaces(); // Does nothing if no handler - event is ignored. if (this.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IHandleBusinessEvent <>) && x.GetGenericArguments()[0] == subscriberEvent.ResolvedEventType)) { await(Task) this.GetType().InvokeMember("HandleBusinessEventAsync", BindingFlags.InvokeMethod, null, this, new object[] { subscriberEvent.StreamId, subscriberEvent.Position, subscriberEvent.ResolvedEvent, cancellationToken }); } }
public void construct() { var parallelKey = "pk"; var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var item = new HandlingQueueItem(parallelKey, subscriberEvent); Assert.Equal(parallelKey, item.ParallelKey); Assert.Equal(subscriberEvent, item.SubscriberEvent); }
public override string SortSubscriberEventToParallelKey(SubscriberEvent subscriberEvent) { if (subscriberEvent.IsResolved) { switch (subscriberEvent.ResolvedEvent) { case SalesOrderRaisedEvent e: return(e.SalesOrderId); } } return(base.SortSubscriberEventToParallelKey(subscriberEvent)); }
public override string SortSubscriberEventToParallelKey(SubscriberEvent subscriberEvent) { if (subscriberEvent.IsResolved) { switch (subscriberEvent.ResolvedEvent) { case EmailEnqueuedEvent e: return(e.EmailId.ToString()); } } return(base.SortSubscriberEventToParallelKey(subscriberEvent)); }
public async Task receive_and_enqueue_subscriber_event() { var cts = new CancellationTokenSource(10000); var mockQueue = new Mock <ISortingQueue>(); var manager = new SortingManager(NullStandardLogger.Instance, mockQueue.Object, null, null); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); mockQueue.Setup(x => x.EnqueueWithWaitAsync(It.IsAny <SubscriberEvent>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); await manager.ReceiveSubscriberEventAsync(subscriberEvent, cts.Token); mockQueue.Verify(x => x.EnqueueWithWaitAsync(subscriberEvent, cts.Token)); }
public async Task throw_when_parallel_key_empty() { var cts = new CancellationTokenSource(10000); var mockQueue = new Mock <ISortingQueue>(); var mockSorter = new Mock <ISubscriberEventSorter>(); var manager = new SortingManager(NullStandardLogger.Instance, mockQueue.Object, mockSorter.Object, null); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = ""; // Must be empty (or null). mockQueue.Setup(x => x.TryDequeue(out subscriberEvent)).Returns(true); mockSorter.Setup(x => x.SortSubscriberEventToParallelKey(subscriberEvent)).Returns(parallelKey); await Assert.ThrowsAsync <ArgumentException>(() => manager.ManageAsync(cts.Token)); }
public async Task honor_max_queue_size() { var cts = new CancellationTokenSource(10000); var maxQueueSize = 2; var mockQueueAwaiter = new Mock <IQueueAwaiter>(); var queue = new HandlingQueue(mockQueueAwaiter.Object, maxQueueSize); var parallelKey1 = "pk1"; var parallelKey2 = "pk2"; var parallelKey3 = "pk3"; var subscriberEvent1 = new SubscriberEvent(null, null, 0, null, null); var subscriberEvent2 = new SubscriberEvent(null, null, 0, null, null); var subscriberEvent3 = new SubscriberEvent(null, null, 0, null, null); var enqueueuSignalSetCount = 0; var awaitingDequeueSignal = new ManualResetEventSlim(true); var mockDequeueSignal = new ManualResetEventSlim(false); mockQueueAwaiter.Setup(x => x.SetEnqueueSignal()).Callback(() => enqueueuSignalSetCount++); mockQueueAwaiter.Setup(x => x.AwaitDequeueSignalAsync()).Callback(() => awaitingDequeueSignal.Set()).Returns(mockDequeueSignal.WaitHandle.AsTask()); await queue.EnqueueWithWaitAsync(parallelKey1, subscriberEvent1, cts.Token); await queue.EnqueueWithWaitAsync(parallelKey2, subscriberEvent2, cts.Token); var enqueueTask = queue.EnqueueWithWaitAsync(parallelKey3, subscriberEvent3, cts.Token); await Task.WhenAny(new[] { awaitingDequeueSignal.WaitHandle.AsTask(), cts.Token.WaitHandle.AsTask() }); if (cts.Token.IsCancellationRequested) { throw new TimeoutException(); } Assert.Equal(2, enqueueuSignalSetCount); Assert.Equal(maxQueueSize, queue.QueueCount); queue.TryDequeue(new string[] { }); Assert.Equal(maxQueueSize - 1, queue.QueueCount); mockDequeueSignal.Set(); await Task.WhenAny(new[] { enqueueTask, cts.Token.WaitHandle.AsTask() }); if (cts.Token.IsCancellationRequested) { throw new TimeoutException(); } Assert.Equal(maxQueueSize, queue.QueueCount); }
public async Task reset_awaiter_when_success() { var mockAwaiter = new Mock <IHandlingManagerAwaiter>(); var mockHandler = new Mock <ISubscriberEventHandler>(); var mockStreamStateRepo = new Mock <IStreamStateRepo>(); var runner = new HandlingManagerHandlerRunner(NullStandardLogger.Instance, mockAwaiter.Object, mockStreamStateRepo.Object, mockHandler.Object); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); mockHandler.Setup(x => x.HandleSubscriberEventAsync(It.IsAny <SubscriberEvent>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); mockStreamStateRepo.Setup(x => x.SaveStreamStateAsync(It.IsAny <string>(), It.IsAny <long>(), It.IsAny <bool>())).Returns(Task.CompletedTask); await runner.TryRunHandlerAsync(subscriberEvent, CancellationToken.None); mockAwaiter.Verify(x => x.ReleaseThrottle()); mockAwaiter.Verify(x => x.SetHandlerCompletionSignal()); }
public async Task enqueue_and_dequeue_single_item() { var cts = new CancellationTokenSource(10000); var maxQueueSize = 1; var mockQueueAwaiter = new Mock <IQueueAwaiter>(); var queue = new SortingQueue(mockQueueAwaiter.Object, maxQueueSize); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); await queue.EnqueueWithWaitAsync(subscriberEvent, cts.Token); SubscriberEvent dequeuedSubscriberEvent; var tryResult = queue.TryDequeue(out dequeuedSubscriberEvent); Assert.True(tryResult); Assert.Equal(subscriberEvent, dequeuedSubscriberEvent); }
public async Task await_throttle_and_run_handler_when_stream_state_does_not_have_error() { var cts = new CancellationTokenSource(); var mockAwaiter = new Mock <IHandlingManagerAwaiter>(); var mockTaskCollection = new Mock <IHandlingManagerTaskCollection>(); var mockQueue = new Mock <IHandlingQueue>(); var mockStreamStateRepo = new Mock <IStreamStateRepo>(); var mockHandlerRunner = new Mock <IHandlingManagerHandlerRunner>(); var manager = new HandlingManager(NullStandardLogger.Instance, mockAwaiter.Object, mockStreamStateRepo.Object, mockQueue.Object, mockHandlerRunner.Object, mockTaskCollection.Object); var businessEvent = new TestBusinessEvent(); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = "x"; var queueItem = new HandlingQueueItem(parallelKey, subscriberEvent); var streamState = new StreamState(0, false); // Does NOT have error. var awaitingThrottleSignal = new ManualResetEventSlim(false); mockQueue.Setup(x => x.IsEventsAvailable).Returns(true); mockQueue.Setup(x => x.TryDequeue(It.IsAny <IList <string> >())).Returns(queueItem); mockQueue.Setup(x => x.AwaitEnqueueSignalAsync()).Callback(() => cts.Cancel()).Returns(Task.CompletedTask); // Ensures manager can't get into an infinite loop. mockStreamStateRepo.Setup(x => x.LoadStreamStateAsync(It.IsAny <string>())).ReturnsAsync(streamState); mockAwaiter.Setup(x => x.AwaitThrottleAsync()).Callback(() => awaitingThrottleSignal.Set()).Returns(Task.CompletedTask); mockHandlerRunner.Setup(x => x.TryRunHandlerAsync(It.IsAny <SubscriberEvent>(), It.IsAny <CancellationToken>())).Callback(() => cts.Cancel()).Returns(Task.CompletedTask); var manageTask = manager.ManageAsync(cts.Token); var timeoutToken1 = new CancellationTokenSource(10000).Token; await Task.WhenAny(new[] { awaitingThrottleSignal.WaitHandle.AsTask(), timeoutToken1.WaitHandle.AsTask() }); if (timeoutToken1.IsCancellationRequested) { cts.Cancel(); throw new TimeoutException(); } var timeoutToken2 = new CancellationTokenSource(10000).Token; await Task.WhenAny(new[] { manageTask, timeoutToken2.WaitHandle.AsTask() }); cts.Cancel(); if (timeoutToken2.IsCancellationRequested) { throw new TimeoutException(); } mockHandlerRunner.Verify(x => x.TryRunHandlerAsync(subscriberEvent, cts.Token)); }
public async Task enqueue_and_not_dequeue_with_matching_parallel_key() { var cts = new CancellationTokenSource(10000); var mockQueueAwaiter = new Mock <IQueueAwaiter>(); var queue = new HandlingQueue(mockQueueAwaiter.Object, 1); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = "pk"; var notInParallelKeys = new List <string>() { parallelKey }; await queue.EnqueueWithWaitAsync(parallelKey, subscriberEvent, cts.Token); var dequeuedItem = queue.TryDequeue(notInParallelKeys); Assert.Null(dequeuedItem); }
public void construct_with_event_not_resolved() { var regionId = "r"; var streamId = "s"; var position = 1; var eventType = "x"; var e = new SubscriberEvent(regionId, streamId, position, eventType, null); Assert.Equal(regionId, e.RegionId); Assert.Equal(streamId, e.StreamId); Assert.Equal(position, e.Position); Assert.Equal(streamId, e.SubscriptionStreamId); Assert.Equal(position, e.SubscriptionPosition); Assert.Equal(eventType, e.EventType); Assert.Null(e.ResolvedEventType); Assert.Null(e.ResolvedEvent); Assert.False(e.IsResolved); }
public async Task run_handler_and_save_errored_stream_state() { var cts = new CancellationTokenSource(); var mockAwaiter = new Mock <IHandlingManagerAwaiter>(); var mockHandler = new Mock <ISubscriberEventHandler>(); var mockStreamStateRepo = new Mock <IStreamStateRepo>(); var runner = new HandlingManagerHandlerRunner(NullStandardLogger.Instance, mockAwaiter.Object, mockStreamStateRepo.Object, mockHandler.Object); var streamId = "s"; var position = 1; var subscriberEvent = new SubscriberEvent(null, streamId, position, null, null); mockHandler.Setup(x => x.HandleSubscriberEventAsync(It.IsAny <SubscriberEvent>(), It.IsAny <CancellationToken>())).Throws(new Exception()); mockStreamStateRepo.Setup(x => x.SaveStreamStateAsync(It.IsAny <string>(), It.IsAny <long>(), It.IsAny <bool>())).Returns(Task.CompletedTask); await runner.TryRunHandlerAsync(subscriberEvent, cts.Token); mockHandler.Verify(x => x.HandleSubscriberEventAsync(subscriberEvent, cts.Token)); mockStreamStateRepo.Verify(x => x.SaveStreamStateAsync(streamId, position, true)); }
public async Task set_queue_signals() { var cts = new CancellationTokenSource(10000); var maxQueueSize = 1; var mockQueueAwaiter = new Mock <IQueueAwaiter>(); var queue = new HandlingQueue(mockQueueAwaiter.Object, maxQueueSize); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = "pk"; queue.TryDequeue(new string[] { }); mockQueueAwaiter.VerifyNoOtherCalls(); await queue.EnqueueWithWaitAsync(parallelKey, subscriberEvent, cts.Token); mockQueueAwaiter.Verify(x => x.SetEnqueueSignal()); mockQueueAwaiter.VerifyNoOtherCalls(); queue.TryDequeue(new string[] { }); mockQueueAwaiter.Verify(x => x.SetDequeueSignal()); }
public async Task sort_subscriber_event_and_send_to_handling_manager() { var cts = new CancellationTokenSource(10000); var mockQueue = new Mock <ISortingQueue>(); var mockSorter = new Mock <ISubscriberEventSorter>(); var mockHandlingManager = new Mock <IHandlingManager>(); var manager = new SortingManager(NullStandardLogger.Instance, mockQueue.Object, mockSorter.Object, mockHandlingManager.Object); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); var parallelKey = "x"; mockQueue.Setup(x => x.TryDequeue(out subscriberEvent)).Returns(true); mockSorter.Setup(x => x.SortSubscriberEventToParallelKey(subscriberEvent)).Returns(parallelKey); mockHandlingManager .Setup(x => x.ReceiveSubscriberEventAsync(It.IsAny <string>(), It.IsAny <SubscriberEvent>(), It.IsAny <CancellationToken>())) .Callback(() => cts.Cancel()) .Returns(Task.CompletedTask); await manager.ManageAsync(cts.Token); mockHandlingManager.Verify(x => x.ReceiveSubscriberEventAsync(parallelKey, subscriberEvent, cts.Token)); }
public void construct_with_event_resolved() { var regionId = "r"; var streamId = "s"; var position = 1; var eventType = "x"; var resolvedEventType = typeof(TestBusinessEvent); var resolvedEvent = new TestBusinessEvent(); var e = new SubscriberEvent(regionId, streamId, position, eventType, resolvedEvent); Assert.Equal(regionId, e.RegionId); Assert.Equal(streamId, e.StreamId); Assert.Equal(position, e.Position); Assert.Equal(streamId, e.SubscriptionStreamId); Assert.Equal(position, e.SubscriptionPosition); Assert.Equal(eventType, e.EventType); Assert.Equal(resolvedEventType, e.ResolvedEventType); Assert.Equal(resolvedEvent, e.ResolvedEvent); Assert.True(e.IsResolved); }
public async Task set_queue_signals() { var cts = new CancellationTokenSource(10000); var maxQueueSize = 1; var mockQueueAwaiter = new Mock <IQueueAwaiter>(); var queue = new SortingQueue(mockQueueAwaiter.Object, maxQueueSize); var subscriberEvent = new SubscriberEvent(null, null, 0, null, null); SubscriberEvent se1; queue.TryDequeue(out se1); mockQueueAwaiter.VerifyNoOtherCalls(); await queue.EnqueueWithWaitAsync(subscriberEvent, cts.Token); mockQueueAwaiter.Verify(x => x.SetEnqueueSignal()); mockQueueAwaiter.VerifyNoOtherCalls(); SubscriberEvent se2; queue.TryDequeue(out se2); mockQueueAwaiter.Verify(x => x.SetDequeueSignal()); }
public Task CreateEvent(SubscriberEvent subscriptionEvent) { throw new NotImplementedException(); }
public HandlingQueueItem(string parallelKey, SubscriberEvent subscriberEvent) { ParallelKey = parallelKey; SubscriberEvent = subscriberEvent; }