public When_the_subscription_runner_processing_a_stream_event_throws_a_detected_stream_gap_exception() { var fixture = new Fixture(); _commandBusMock = new Mock <IConnectedProjectionsCommandBus>(); var streamMock = new Mock <IConnectedProjectionsStreamStoreSubscription>(); streamMock .SetupGet(stream => stream.StreamIsRunning) .Returns(true); var contextMock = new Mock <IConnectedProjectionContext <FakeProjectionContext> >(); contextMock .Setup(context => context.GetProjectionPosition(It.IsAny <ConnectedProjectionIdentifier>(), It.IsAny <CancellationToken>())) .ReturnsAsync((long?)null); var missingMessagesPositions = fixture.CreateMany <long>(2, 10).ToList(); _registeredProjections = new List <IConnectedProjection> { new FakeProjection( $"{MissingMessageProjectionIdentifier}-1", ThrowMissingMessageException(missingMessagesPositions), contextMock.Object), new FakeProjection( "do-nothing", (messages, strategy, name, ct) => Task.CompletedTask, contextMock.Object), new FakeProjection( $"{MissingMessageProjectionIdentifier}-2", ThrowMissingMessageException(missingMessagesPositions), contextMock.Object) }; var registeredProjectionsMock = new Mock <IRegisteredProjections>(); registeredProjectionsMock .Setup(projections => projections.GetProjection(It.IsAny <ConnectedProjectionIdentifier>())) .Returns((ConnectedProjectionIdentifier projectionId) => _registeredProjections.FirstOrDefault(projection => projection.Id.Equals(projectionId))); var loggerFactory = new FakeLoggerFactory(); _loggerMock = loggerFactory.ResolveLoggerMock <ConnectedProjectionsSubscriptionRunner>(); _gapStrategySettings = fixture.Create <StreamGapStrategyConfigurationSettings>(); var gapStrategyMock = new Mock <IStreamGapStrategy>(); gapStrategyMock .SetupGet(strategy => strategy.Settings) .Returns(_gapStrategySettings); _sut = new ConnectedProjectionsSubscriptionRunner( registeredProjectionsMock.Object, streamMock.Object, _commandBusMock.Object, gapStrategyMock.Object, loggerFactory); foreach (var projection in _registeredProjections) { _sut.HandleSubscriptionCommand(new Subscribe(projection.Id)).GetAwaiter(); } VerifySetup(); _sut.HandleSubscriptionCommand(new ProcessStreamEvent(fixture.Create <StreamMessage>(), fixture.Create <CancellationToken>())).GetAwaiter(); }
public When_a_projection_catch_up_processes_a_stream_and_throws_a_detected_stream_gap_exception() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); var contextMock = new Mock <IConnectedProjectionContext <FakeProjectionContext> >(); contextMock .Setup(context => context.GetProjectionPosition(It.IsAny <ConnectedProjectionIdentifier>(), It.IsAny <CancellationToken>())) .ReturnsAsync((long?)null); var streamMock = new Mock <IReadonlyStreamStore>(); streamMock .Setup(store => store.ReadAllForwards( It.IsAny <long>(), It.IsAny <int>(), It.IsAny <bool>(), It.IsAny <CancellationToken>())) .ReturnsAsync(() => { var position = fixture.CreatePositive <long>().WithMaximumValueOf(long.MaxValue - 1000); return(new ReadAllPage( position, position.CreateRandomHigherValue(), true, ReadDirection.Forward, (p, token) => throw new NotImplementedException(), fixture.CreateMany <StreamMessage>(2, 10).ToArray())); }); _commandBusMock = new Mock <IConnectedProjectionsCommandBus>(); _gapStrategySettings = fixture.Create <StreamGapStrategyConfigurationSettings>(); var gapStrategyMock = new Mock <IStreamGapStrategy>(); gapStrategyMock .SetupGet(strategy => strategy.Settings) .Returns(_gapStrategySettings); _loggerMock = new FakeLogger(); _projection = new FakeProjection( "catch-up-dummy", (messages, strategy, name, ct) => throw new ConnectedProjectionMessageHandlingException( new StreamGapDetectedException(fixture.CreateMany <long>(1, 10), name), name, new ActiveProcessedStreamState(0)), contextMock.Object); var sut = new ConnectedProjectionCatchUp <FakeProjectionContext>( _projection, ConnectedProjectionSettings.Default, streamMock.Object, _commandBusMock.Object, gapStrategyMock.Object, _loggerMock.AsLogger()); sut.CatchUpAsync(CancellationToken.None).GetAwaiter(); }
public When_handling_a_message_with_position_within_and_creation_outside_stream_end_buffer_using_the_default_catchup_stream_gap_strategy() { var fixture = new Fixture() .CustomizeConnectedProjectionIdentifiers(); _projection = fixture.Create <ConnectedProjectionIdentifier>(); _missingPositions = fixture.CreateMany <long>(1, 10); var settings = new StreamGapStrategyConfigurationSettings { StreamBufferInSeconds = fixture.CreatePositive <int>(), PositionBufferSize = fixture.CreatePositive <int>() }; var streamHeadPosition = fixture .CreatePositive <long>() .WithMinimumValueOf(settings.PositionBufferSize + 100); var streamStoreMock = new Mock <IReadonlyStreamStore>(); streamStoreMock .Setup(store => store.ReadHeadPosition(It.IsAny <CancellationToken>())) .Returns(Task.FromResult(streamHeadPosition)); var now = fixture .Create <DateTime>() .ToUniversalTime(); var clockMock = new Mock <IClock>(); clockMock .Setup(clock => clock.GetCurrentInstant()) .Returns(Instant.FromDateTimeUtc(now)); var message = (StreamMessage)fixture .Build <ConfigurableStreamMessage>() .WithPosition(streamHeadPosition .CreateRandomLowerValue() .WithMinimumValueOf(streamHeadPosition + 1 - settings.PositionBufferSize)) .WithCreatedUtc(now.AddSeconds(0 - settings.StreamBufferInSeconds)) .Create(); var stateMock = new Mock <IProcessedStreamState>(); stateMock .Setup(state => state.DetermineGapPositions(message)) .Returns(_missingPositions); var fakeLoggerFactory = new FakeLoggerFactory(); _loggerMock = fakeLoggerFactory.ResolveLoggerMock <DefaultCatchUpStreamGapStrategy>(); _processMessageFunctionStatus = "NotExecuted"; new DefaultCatchUpStreamGapStrategy(fakeLoggerFactory, settings, streamStoreMock.Object, clockMock.Object) .HandleMessage( message, stateMock.Object, (_, token) => { _processMessageFunctionStatus = "Executed"; return(Task.CompletedTask); }, _projection, fixture.Create <CancellationToken>()) .GetAwaiter(); }