private async Task DoAndUpdateStateAsync(Func <Task> action) { try { await action(); await eventConsumerInfoRepository.SetAsync(eventConsumer.Name, statusPosition, !statusIsRunning, statusError); } catch (Exception ex) { try { Unsubscribe(); } catch (Exception unsubscribeException) { ex = new AggregateException(ex, unsubscribeException); } log.LogFatal(ex, w => w .WriteProperty("action", "HandleEvent") .WriteProperty("state", "Failed") .WriteProperty("eventConsumer", eventConsumer.Name)); statusError = ex.ToString(); statusIsRunning = false; await eventConsumerInfoRepository.SetAsync(eventConsumer.Name, statusPosition, !statusIsRunning, statusError); } }
public async Task Should_stop_subscription_when_stopped() { await OnSubscribeAsync(); sutActor.Tell(new StopConsumerMessage()); sutActor.Tell(new StopConsumerMessage()); sut.Dispose(); A.CallTo(() => eventConsumerInfoRepository.SetAsync(consumerName, consumerInfo.Position, true, null)) .MustHaveHappened(Repeated.Exactly.Once); A.CallTo(() => eventSubscription.StopAsync()) .MustHaveHappened(Repeated.Exactly.Once); }
private async Task OnMessage(object message) { if (isStopped) { return; } try { var oldStateId = stateId; var newStateId = stateId = Guid.NewGuid(); switch (message) { case Teardown teardown: { isStopped = true; return; } case Setup setup: { eventConsumer = setup.EventConsumer; var status = await eventConsumerInfoRepository.FindAsync(eventConsumer.Name); if (status != null) { statusError = status.Error; statusPosition = status.Position; statusIsRunning = !status.IsStopped; } if (statusIsRunning) { await SubscribeThisAsync(statusPosition); } break; } case StartConsumerMessage startConsumer: { if (statusIsRunning) { return; } await SubscribeThisAsync(statusPosition); statusError = null; statusIsRunning = true; break; } case StopConsumerMessage stopConsumer: { if (!statusIsRunning) { return; } await UnsubscribeThisAsync(); statusIsRunning = false; break; } case ResetConsumerMessage resetConsumer: { await UnsubscribeThisAsync(); await ClearAsync(); await SubscribeThisAsync(null); statusError = null; statusPosition = null; statusIsRunning = true; break; } case Reconnect reconnect: { if (!statusIsRunning || reconnect.StateId != oldStateId) { return; } await SubscribeThisAsync(statusPosition); break; } case SubscriptionFailed subscriptionFailed: { if (subscriptionFailed.Subscription != eventSubscription) { return; } await UnsubscribeThisAsync(); if (retryWindow.CanRetryAfterFailure()) { Task.Delay(ReconnectWaitMs).ContinueWith(t => dispatcher.SendAsync(new Reconnect { StateId = newStateId })).Forget(); } else { throw subscriptionFailed.Exception; } break; } case SubscriptionEventReceived eventReceived: { if (eventReceived.Subscription != eventSubscription) { return; } var @event = ParseEvent(eventReceived.Event); await DispatchConsumerAsync(@event); statusError = null; statusPosition = @eventReceived.Event.EventPosition; break; } } await eventConsumerInfoRepository.SetAsync(eventConsumer.Name, statusPosition, !statusIsRunning, statusError); } catch (Exception ex) { try { await UnsubscribeThisAsync(); } catch (Exception unsubscribeException) { ex = new AggregateException(ex, unsubscribeException); } log.LogFatal(ex, w => w .WriteProperty("action", "HandleEvent") .WriteProperty("state", "Failed") .WriteProperty("eventConsumer", eventConsumer.Name)); statusError = ex.ToString(); statusIsRunning = false; await eventConsumerInfoRepository.SetAsync(eventConsumer.Name, statusPosition, !statusIsRunning, statusError); } }
public async Task Should_subscribe_to_event_store_when_not_found_in_db() { A.CallTo(() => eventConsumerInfoRepository.FindAsync(consumerName)).Returns(Task.FromResult <IEventConsumerInfo>(null)); await OnSubscribeAsync(); sut.Dispose(); A.CallTo(() => eventConsumerInfoRepository.SetAsync(consumerName, null, false, null)) .MustHaveHappened(Repeated.Exactly.Once); A.CallTo(() => eventStore.CreateSubscription(A <IEventSubscriber> .Ignored, A <string> .Ignored, A <string> .Ignored)) .MustHaveHappened(Repeated.Exactly.Once); }