public When_handling_a_message_using_the_default_subscription_stream_gap_strategy() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); _projection = fixture.Create <ConnectedProjectionIdentifier>(); _missingPositions = fixture.CreateMany <long>(1, 10); var message = fixture.Create <StreamMessage>(); var stateMock = new Mock <IProcessedStreamState>(); stateMock .Setup(state => state.DetermineGapPositions(message)) .Returns(_missingPositions); _processMessageFunctionStatus = "NotExecuted"; _handlingMessage = async() => await new DefaultSubscriptionStreamGapStrategy(Mock.Of <IStreamGapStrategyConfigurationSettings>()) .HandleMessage( message, stateMock.Object, (_, token) => { _processMessageFunctionStatus = "Executed"; return(Task.CompletedTask); }, _projection, fixture.Create <CancellationToken>()); }
public WhenMessageHandlerThrowsExceptionsDefinedByRetryPolicy() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); var exceptionSequence = fixture .CreateMany <RetryException>(2, 10) .ToArray <Exception>(); _loggerMock = new FakeLoggerFactory().ResolveLoggerMock <MessageHandlerWithExecutionTracking>(); _projection = fixture.Create <ConnectedProjectionIdentifier>(); _handlerWithoutPolicy = new MessageHandlerWithExecutionTracking( _projection, _loggerMock.AsLogger(), exceptionSequence); _numberOfRetries = exceptionSequence.Length; _numberOfExpectedAttempts = Times.Exactly(1 + _numberOfRetries); _initialWait = TimeSpan.FromMilliseconds(fixture.CreatePositive <int>()); _messages = fixture.CreateMany <StreamMessage>().ToList(); new LinearBackOff <RetryException>(_numberOfRetries, _initialWait) .ApplyOn(_handlerWithoutPolicy) .HandleAsync(_messages, Mock.Of <IStreamGapStrategy>(), CancellationToken.None) .GetAwaiter() .GetResult(); }
protected override async Task Setup() { _waitForProjection = new AutoResetEvent(false); _projection = new ConnectedProjectionIdentifier(typeof(TrackHandledEventsProjection)); await PushToStream(Fixture.Create <SomethingHappened>()); await PushToStream(Fixture.Create <DelayWasScheduled>()); }
public async Task SetErrorMessage( ConnectedProjectionIdentifier projection, Exception exception, CancellationToken cancellationToken) { //exception.ToString() => https://stackoverflow.com/a/2176722/412692 await _context.SetErrorMessage(projection, exception.ToString(), cancellationToken); }
public async Task <long?> GetProjectionPosition( ConnectedProjectionIdentifier projection, CancellationToken cancellationToken) { var state = await GetProjectionState(projection, cancellationToken); return(state?.Position); }
public async Task UpdateProjectionDesiredState( ConnectedProjectionIdentifier projection, UserDesiredState userDesiredState, CancellationToken cancellationToken) => await _context.UpdateProjectionDesiredState( projection, userDesiredState, CancellationToken.None);
public ProjectionMock(ConnectedProjectionIdentifier projectionId) { ProjectionId = projectionId; Projection = new Mock <IConnectedProjection>(); Projection .Setup(connectedProjection => connectedProjection.ShouldResume(It.IsAny <CancellationToken>())) .ReturnsAsync(() => _shouldResume); }
public RegisteredConnectedProjection( ConnectedProjectionIdentifier id, ConnectedProjectionState state, ConnectedProjectionInfo info) { Id = id; State = state; Info = info; }
public async Task UpdateProjectionPosition( ConnectedProjectionIdentifier projection, long position, CancellationToken cancellationToken) => await _context .UpdateProjectionState( projection.ToString(), position, cancellationToken);
public MessageHandlerWithExecutionTracking( ConnectedProjectionIdentifier projection, ILogger logger, params Exception[] exceptionSequence) { Projection = projection; Logger = logger; _exceptionSequence = new Stack <Exception>(exceptionSequence.Reverse()); }
public async Task <UserDesiredState?> GetProjectionDesiredState( ConnectedProjectionIdentifier projection, CancellationToken cancellationToken) { var projectionState = await GetProjectionState(projection, cancellationToken); return(UserDesiredState.TryParse(projectionState?.DesiredState ?? string.Empty, out var state) ? state : null); }
public async Task <ProjectionStateItem?> GetProjectionState( ConnectedProjectionIdentifier projection, CancellationToken cancellationToken) { return(await _context .ProjectionStates .AsNoTracking() .SingleOrDefaultAsync( item => item.Name == projection.ToString(), cancellationToken)); }
public ConnectedProjectionMessageHandler( ConnectedProjectionIdentifier projection, ConnectedProjectionHandler <TContext>[] handlers, Func <Owned <IConnectedProjectionContext <TContext> > > contextFactory, ILoggerFactory loggerFactory) { Projection = projection; _contextFactory = contextFactory ?? throw new ArgumentNullException(nameof(contextFactory)); _projector = new ConnectedProjector <TContext>(Resolve.WhenEqualToHandlerMessageType(handlers)); Logger = loggerFactory?.CreateLogger <ConnectedProjectionMessageHandler <TContext> >() ?? throw new ArgumentNullException(nameof(loggerFactory)); }
public async Task Stop(string id, CancellationToken cancellationToken) { var projection = new ConnectedProjectionIdentifier(id); if (!_registeredProjections.Exists(projection)) { return; // throw new ArgumentException("Invalid projection Id.", nameof(projection)); } await _registeredProjections .GetProjection(projection) .UpdateUserDesiredState(UserDesiredState.Stopped, cancellationToken); _commandBus.Queue(new Stop(projection)); }
protected override async Task Setup() { _waitForProjection = new AutoResetEvent(false); _projection = new ConnectedProjectionIdentifier(typeof(TrackHandledEventsProjection)); await PushToStream(Fixture.Create <SomethingHappened>()); await ProjectionManager.Start(CancellationToken.None); _waitForProjection.WaitOne(); _waitForProjection.Reset(); await ProjectionManager.Stop(CancellationToken.None); await Task.Delay(500); }
public When_handling_a_message_with_a_position_that_does_follow_the_previous_message_position() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); _projectionId = fixture.Create <ConnectedProjectionIdentifier>(); var contextMock = new Mock <IConnectedProjectionContext <ProjectionContext> >(); var runnerPosition = fixture .CreatePositive <long>() .WithMaximumValueOf(long.MaxValue - 100); contextMock .Setup(context => context.GetProjectionPosition(_projectionId, It.IsAny <CancellationToken>())) .ReturnsAsync(runnerPosition); var sut = new ConnectedProjectionMessageHandler <ProjectionContext>( _projectionId, Array.Empty <ConnectedProjectionHandler <ProjectionContext> >(), contextMock.CreateOwnedObject, new FakeLoggerFactory() ); _message1 = fixture .Build <ConfigurableStreamMessage>() .With(streamMessage => streamMessage.Position, runnerPosition + 1) .Create(); _message2 = fixture .Build <ConfigurableStreamMessage>() .With(streamMessage => streamMessage.Position, _message1.Position + 1) .Create(); _streamGapStrategyMock = new Mock <IStreamGapStrategy>(); _streamGapStrategyMock .Setup(strategy => strategy.HandleMessage( It.IsAny <StreamMessage>(), It.IsAny <IProcessedStreamState>(), It.IsAny <Func <StreamMessage, CancellationToken, Task> >(), _projectionId, It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask); sut.HandleAsync( new[] { _message1, _message2 }, _streamGapStrategyMock.Object, CancellationToken.None) .GetAwaiter(); }
private void StopCatchUp(ConnectedProjectionIdentifier projection) { if (projection == null || IsCatchingUp(projection) == false) { return; } try { using (var catchUp = _projectionCatchUps[projection]) catchUp.Cancel(); } catch (KeyNotFoundException) { } catch (ObjectDisposedException) { } }
public async Task HandleMessage( StreamMessage message, IProcessedStreamState state, Func <StreamMessage, CancellationToken, Task> executeProjectMessage, ConnectedProjectionIdentifier projection, CancellationToken cancellationToken) { if (await IsCloseToStreamEnd(message, cancellationToken)) { throw new StreamGapDetectedException(state.DetermineGapPositions(message), projection); } _logger.LogWarning( "Expected messages at positions [{UnprocessedPositions}] were not processed for {Projection}.", string.Join(", ", state.DetermineGapPositions(message)), projection); await executeProjectMessage(message, cancellationToken); }
public FakeProjection( string id, Func <IEnumerable <StreamMessage>, IStreamGapStrategy, ConnectedProjectionIdentifier, CancellationToken, Task> messageHandler, IConnectedProjectionContext <FakeProjectionContext> context) { Id = new ConnectedProjectionIdentifier($"{GetType().FullName}-{id}"); Info = new ConnectedProjectionInfo(string.Empty, string.Empty); var messageHandlerMock = new Mock <IConnectedProjectionMessageHandler>(); messageHandlerMock .SetupGet(handler => handler.Projection) .Returns(Id); messageHandlerMock .Setup(handler => handler.HandleAsync(It.IsAny <IEnumerable <StreamMessage> >(), It.IsAny <IStreamGapStrategy>(), It.IsAny <CancellationToken>())) .Returns((IEnumerable <StreamMessage> messages, IStreamGapStrategy strategy, CancellationToken ct) => messageHandler(messages, strategy, Id, ct)); ConnectedProjectionMessageHandler = messageHandlerMock.Object; ContextFactory = () => new Owned <IConnectedProjectionContext <FakeProjectionContext> >(context, Mock.Of <IDisposable>()); }
public WhenMessageHandlerThrowsAnExceptionThatWasNotDefinedToRetryAfterRetrying() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); _exceptionSequence = new Exception[] { new RetryException(), new DoNotRetryException() }; _loggerMock = new FakeLoggerFactory().ResolveLoggerMock <MessageHandlerWithExecutionTracking>(); _projection = fixture.Create <ConnectedProjectionIdentifier>(); _handlerWithoutPolicy = new MessageHandlerWithExecutionTracking( _projection, _loggerMock.AsLogger(), _exceptionSequence); var numberOfRetries = _exceptionSequence.Count(exception => exception is RetryException); _numberOfExpectedAttempts = Times.Exactly(1 + numberOfRetries); _initialWait = TimeSpan.FromMilliseconds(fixture.CreatePositive <int>()); _messages = fixture.CreateMany <StreamMessage>().ToList(); _sut = new LinearBackOff <RetryException>(numberOfRetries, _initialWait) .ApplyOn(_handlerWithoutPolicy); }
public WhenMessageHandlerThrowsTheExceptionDefinedInThePolicyMoreThanTheNumberOfRetries() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); var exceptionSequence = fixture .CreateMany <RetryException>(2, 10) .ToArray <Exception>(); _loggerMock = new FakeLoggerFactory().ResolveLoggerMock <MessageHandlerWithExecutionTracking>(); _projection = fixture.Create <ConnectedProjectionIdentifier>(); _handlerWithoutPolicy = new MessageHandlerWithExecutionTracking( _projection, _loggerMock.AsLogger(), exceptionSequence); _numberOfRetries = exceptionSequence.Length - 1; _numberOfExpectedAttempts = Times.Exactly(1 + _numberOfRetries); _initialWait = TimeSpan.FromMilliseconds(fixture.CreatePositive <int>()); _messages = fixture.CreateMany <StreamMessage>().ToList(); _sut = new LinearBackOff <RetryException>(_numberOfRetries, _initialWait) .ApplyOn(_handlerWithoutPolicy); }
public StreamGapDetectedException(IEnumerable <long> missingPositions, ConnectedProjectionIdentifier projection) : base($"Stream does not contain messages at positions [{string.Join(',', missingPositions)}] for projection {projection}") { }
public async Task ClearErrorMessage( ConnectedProjectionIdentifier projection, CancellationToken cancellationToken) => await _context.SetErrorMessage(projection, null, cancellationToken);
private ConnectedProjectionState GetStateFor(ConnectedProjectionIdentifier projection) => ProjectionManager .GetRegisteredProjections() .Single(connectedProjection => connectedProjection.Id == projection) .State;
protected override Task Setup() { _projection = new ConnectedProjectionIdentifier(typeof(TrackHandledEventsProjection)); _projectionStarted = new AutoResetEvent(false); return(Task.CompletedTask); }
public StopCatchUp(ConnectedProjectionIdentifier projection) => Projection = projection ?? throw new ArgumentNullException(nameof(projection));
public Subscribe(ConnectedProjectionIdentifier projection) => Projection = projection ?? throw new ArgumentNullException(nameof(projection));
internal bool HasSubscription(ConnectedProjectionIdentifier projection) => projection != null && _handlers.ContainsKey(projection);
public void When_creating_connected_projection_identifier_from_a_type_then_identifier_is_the_fully_qualified_name() { var identifier = new ConnectedProjectionIdentifier(typeof(ConnectedProjectionIdentifierTests)); identifier.Should().Be("Be.Vlaanderen.Basisregisters.Projector.Tests.ConnectedProjectionIdentifierTests"); }
public ConnectedProjectionMessageHandlingException(Exception exception, ConnectedProjectionIdentifier projection, IProcessedStreamState?processedState) : base($"Error occured handling message at position: {processedState?.LastProcessedMessagePosition}", exception) { Projection = projection; RunnerPosition = processedState?.LastProcessedMessagePosition ?? -1L; }