コード例 #1
0
        public async Task CanSubscribeToStream()
        {
            var streamMessageReceived = false;
            var subscriptionDropped   = false;

            var streamStore = new InMemoryStreamStore();
            var streamId    = new StreamId("test");

            streamStore.SubscribeToStream(streamId, null, StreamMessageReceived, SubscriptionDropped);

            var message = new NewStreamMessage(Guid.NewGuid(), "Test", @"{ 'Hello': 'World' }");
            await streamStore.AppendToStream(streamId, ExpectedVersion.Any, message);

            Thread.Sleep(100);

            Assert.True(streamMessageReceived);
            Assert.False(subscriptionDropped);

            async Task StreamMessageReceived(IStreamSubscription subscription, StreamMessage streamMessage, CancellationToken cancellationToken)
            {
                streamMessageReceived = true;
                Assert.Equal("Test", streamMessage.Type);
            }

            void SubscriptionDropped(IStreamSubscription subscription, SubscriptionDroppedReason reason, Exception exception = null)
            {
                subscriptionDropped = true;
            }
        }
コード例 #2
0
        public async Task When_exception_throw_by_subscription_message_received_then_should_drop_subscription()
        {
            using (var store = new InMemoryStreamStore())
            {
                var eventReceivedException            = new TaskCompletionSource <Exception>();
                StreamMessageReceived messageReceived = _ =>
                {
                    throw new Exception();
                };
                SubscriptionDropped subscriptionDropped = (reason, exception) =>
                {
                    eventReceivedException.SetResult(exception);
                };
                string streamId = "stream-1";
                using (await store.SubscribeToStream("stream-1", StreamVersion.Start, messageReceived, subscriptionDropped))
                {
                    await store.AppendToStream(streamId,
                                               ExpectedVersion.NoStream,
                                               new NewStreamMessage(Guid.NewGuid(), "type", "{}"));

                    var dropException = await eventReceivedException.Task.WithTimeout();

                    dropException.ShouldBeOfType <Exception>();
                }
            }
        }
        public async Task DoesNotAppendEventWhenLastEventIsFromSameDay()
        {
            var now                 = new DateTime(2019, 12, 25, 12, 00, 00);
            var utcNow              = now.ToUniversalTime();
            var clockProviderStub   = new ClockProviderStub(now);
            var inMemoryStreamStore = new InMemoryStreamStore(() => utcNow);
            var clockHasTicked      = new ClockHasTicked(new DateTime(2019, 12, 25, 11, 00, 00));

            var cancellationToken = CancellationToken.None;
            await inMemoryStreamStore.AppendToStream(
                streamId : new StreamId(ClockTickingService.ClockStreamId),
                expectedVersion : ExpectedVersion.Any,
                message : new NewStreamMessage(
                    messageId: Guid.NewGuid(),
                    type: _eventMapping.GetEventName(clockHasTicked.GetType()),
                    jsonData: JsonConvert.SerializeObject(clockHasTicked)),
                cancellationToken : cancellationToken);

            var sut = new ClockTickingService(inMemoryStreamStore, clockProviderStub);

            await sut.StartAsync(cancellationToken);

            var forwards = await inMemoryStreamStore.ReadAllForwards(Position.Start, Int32.MaxValue, true, cancellationToken);

            forwards.Messages.Should().HaveCount(1);
        }
コード例 #4
0
        public async Task CanAppendToMultipleStreamsAndReadAllForward()
        {
            var streamStore = new InMemoryStreamStore();
            var stream1     = new StreamId("test1");
            var stream2     = new StreamId("test2");

            var message1 = new NewStreamMessage(Guid.NewGuid(), "Test1", @"{ 'Hello': 'World1' }");
            await streamStore.AppendToStream(stream1, ExpectedVersion.Any, message1);

            var message2 = new NewStreamMessage(Guid.NewGuid(), "Test2", @"{ 'Hello': 'World2' }");
            await streamStore.AppendToStream(stream2, ExpectedVersion.Any, message2);

            var readStreamPage = await streamStore.ReadAllForwards(StreamVersion.Start, int.MaxValue, true);

            Assert.Equal(2, readStreamPage.Messages.Length);
        }
コード例 #5
0
        public void CreateDependencies()
        {
            var store        = new InMemoryStreamStore();
            var eventMapping = new EventMapping(new Dictionary <string, Type>
            {
                { "SomethingHappened", typeof(SomethingHappened) },
                { "SomethingElseHappened", typeof(SomethingElseHappened) },
            });
            var eventSerializer   = new EventSerializer(JsonConvert.SerializeObject);
            var eventDeserializer = new EventDeserializer(JsonConvert.DeserializeObject);

            _factRepository = new StreamStoreFactRepository(store, eventMapping, eventSerializer, eventDeserializer);

            _handlerFactory = (eventType, @events) =>
                              async(command) =>
            {
                long position = 0;
                foreach (var @event in events)
                {
                    position = (await store.AppendToStream(
                                    (command as DoSomething).Identifier,
                                    ExpectedVersion.Any,
                                    new NewStreamMessage(Guid.NewGuid(), eventType,
                                                         eventSerializer.SerializeObject(@event)),
                                    CancellationToken.None)
                                ).CurrentPosition;
                }

                return(position);
            };
            _handlerResolver = new Mocking <IHandlerResolver, HandlerResolverSetup>();
            //_handlerResolver.When().ResolvesHandler(_handlerFactory);
        }
コード例 #6
0
        private Func <TestMessage, Task <AppendResult> > CreateMessageStorerAndStartHandling(ConnectedProjection <TestDbContext> projection)
        {
            var eventMapping =
                new EventMapping(EventMapping.DiscoverEventNamesInAssembly(typeof(RunnerTests).Assembly));
            var testRunner =
                new TestRunner(
                    new EnvelopeFactory(
                        eventMapping,
                        new EventDeserializer(JsonConvert.DeserializeObject)),
                    new Logger <TestRunner>(new LoggerFactory()),
                    projection);

            var options = new DbContextOptionsBuilder <TestDbContext>()
                          .UseInMemoryDatabase("testing")
                          .Options;

            using (var testDbContext = new TestDbContext(options))
            {
                testDbContext.Database.EnsureDeleted();
            }

            var inMemoryStreamStore = new InMemoryStreamStore(() => DateTime.UtcNow);

            testRunner.Handle(
                inMemoryStreamStore,
                () => new Owned <TestDbContext>(new TestDbContext(options), this));

            return(async message => await inMemoryStreamStore.AppendToStream(new StreamId("Bla"), ExpectedVersion.Any,
                                                                             new NewStreamMessage(Guid.NewGuid(), eventMapping.GetEventName(typeof(TestMessage)), JsonConvert.SerializeObject(message))));
        }
コード例 #7
0
        public async Task AppendToStreamWithWrongExpectedVersionThrowsException()
        {
            var streamStore = new InMemoryStreamStore();
            var stremId     = new StreamId("test");

            var jsonIn  = @"{ 'Hello': 'World' }";
            var message = new NewStreamMessage(Guid.NewGuid(), "Test", jsonIn);
            await streamStore.AppendToStream(stremId, ExpectedVersion.NoStream, message);

            jsonIn  = @"{ 'Hello': 'New World' }";
            message = new NewStreamMessage(Guid.NewGuid(), "Test", jsonIn);
            await streamStore.AppendToStream(stremId, 0, message);

            jsonIn  = @"{ 'Hello': 'Very New World' }";
            message = new NewStreamMessage(Guid.NewGuid(), "Test", jsonIn);
            await Assert.ThrowsAsync(typeof(WrongExpectedVersionException), async() => { await streamStore.AppendToStream(stremId, 0, message); });
        }
コード例 #8
0
        public async Task ShowWithCatchupSubscription()
        {
            //setup a projection schema (one of many ways)
            var projector = new SqlProjector(
                Resolve.WhenEqualToHandlerMessageType(new PortfolioProjection()),
                new TransactionalSqlCommandExecutor(
                    new ConnectionStringSettings(
                        "projac",
                        @"Data Source=(localdb)\ProjectsV12;Initial Catalog=ProjacUsage;Integrated Security=SSPI;",
                        "System.Data.SqlClient"),
                    IsolationLevel.ReadCommitted));

            projector.Project(new object[] { new DropSchema(), new CreateSchema() });

            //setup a memory eventstore
            var store = new InMemoryStreamStore();

            //setup a sample stream (using some sample events)
            var portfolioId = Guid.NewGuid();
            var events      = new object[]
            {
                new PortfolioAdded {
                    Id = portfolioId, Name = "My Portfolio"
                },
                new PortfolioRenamed {
                    Id = portfolioId, Name = "Your Portfolio"
                },
                new PortfolioRemoved {
                    Id = portfolioId
                }
            };
            var stream = string.Format("portfolio-{0}", portfolioId.ToString("N"));
            await store.AppendToStream(
                stream,
                ExpectedVersion.Any,
                events
                .Select(@event => new NewStreamMessage(
                            Guid.NewGuid(),
                            @event.GetType().FullName,
                            JsonConvert.SerializeObject(@event)))
                .ToArray());

            //project the sample stream (until end of stream)
            var subscription = store.SubscribeToStream(stream, null, async(_, rawMessage) =>
            {
                var @event = JsonConvert.DeserializeObject(
                    await rawMessage.GetJsonData(),
                    Type.GetType(rawMessage.Type, true));

                projector.Project(@event);
            });
            //should complete within 5 seconds.
            await Task.Delay(TimeSpan.FromSeconds(5));

            subscription.Dispose();
        }
コード例 #9
0
        public async Task CreatingANewStreamTest(int expectedVersion, int currentVersionForOpenedStream)
        {
            var streamId    = "newStreamId1";
            var streamStore = new InMemoryStreamStore();
            var result      = await streamStore.AppendToStream(new StreamId(streamId), expectedVersion, new NewStreamMessage[0],
                                                               CancellationToken.None);

            Assert.AreEqual(-1, result.CurrentPosition);
            Assert.AreEqual(currentVersionForOpenedStream, result.CurrentVersion);
        }
コード例 #10
0
        public async Task CanSubscribeToAllStreams()
        {
            var receivedMessagesCount = 0;
            var subscriptionDropped   = false;

            var streamStore = new InMemoryStreamStore();
            var stream1     = new StreamId("test1");
            var stream2     = new StreamId("test2");

            streamStore.SubscribeToAll(null, AllStreamMessageReceived, AllSubscriptionDropped);

            var message1 = new NewStreamMessage(Guid.NewGuid(), "Test1", @"{ 'Hello': 'World1' }");
            await streamStore.AppendToStream(stream1, ExpectedVersion.Any, message1);

            var message2 = new NewStreamMessage(Guid.NewGuid(), "Test2", @"{ 'Hello': 'World2' }");
            await streamStore.AppendToStream(stream2, ExpectedVersion.Any, message2);

            Thread.Sleep(100);

            Assert.Equal(2, receivedMessagesCount);
            Assert.False(subscriptionDropped);

            async Task AllStreamMessageReceived(IAllStreamSubscription subscription, StreamMessage streamMessage, CancellationToken cancellationToken)
            {
                if (receivedMessagesCount == 0)
                {
                    Assert.Equal("Test1", streamMessage.Type);
                }

                if (receivedMessagesCount == 1)
                {
                    Assert.Equal("Test2", streamMessage.Type);
                }

                receivedMessagesCount++;
            }

            void AllSubscriptionDropped(IAllStreamSubscription subscription, SubscriptionDroppedReason reason, Exception exception = null)
            {
                subscriptionDropped = true;
            }
        }
コード例 #11
0
        public void CreatingANonExistingStreamWithVersionAsEmptyStreamThrowsException(int expectedVersion)
        {
            var streamId    = "newStreamId1";
            var streamStore = new InMemoryStreamStore();

            Assert.ThrowsAsync <WrongExpectedVersionException> (async() =>
            {
                var result = await streamStore.AppendToStream(new StreamId(streamId), expectedVersion, new NewStreamMessage[0],
                                                              CancellationToken.None);
            });
        }
コード例 #12
0
        public async Task CanGetStreamVersion()
        {
            var streamStore = new InMemoryStreamStore();
            var stream1     = new StreamId("test1");
            var stream2     = new StreamId("test2");

            var message1 = new NewStreamMessage(Guid.NewGuid(), "Test1", @"{ 'Hello': 'World1' }");
            await streamStore.AppendToStream(stream1, ExpectedVersion.Any, message1);

            message1 = new NewStreamMessage(Guid.NewGuid(), "Test1", @"{ 'Hello': 'World1' }");
            await streamStore.AppendToStream(stream1, ExpectedVersion.Any, message1);

            var message2 = new NewStreamMessage(Guid.NewGuid(), "Test2", @"{ 'Hello': 'World2' }");
            await streamStore.AppendToStream(stream2, ExpectedVersion.Any, message2);

            Thread.Sleep(100);

            var stream1Metadata = await streamStore.GetStreamMetadata("test1");

            var stream2Metadata = await streamStore.GetStreamMetadata("test2");

            Assert.Equal(1, stream1Metadata.MetadataStreamVersion);
            Assert.Equal(0, stream2Metadata.MetadataStreamVersion);
        }
コード例 #13
0
        public async Task CanAppendToStreamAndReadFromStreamForwardAndGetJsonBack()
        {
            var streamStore = new InMemoryStreamStore();
            var stremId     = new StreamId("test");

            var jsonIn  = @"{ 'Hello': 'World' }";
            var message = new NewStreamMessage(Guid.NewGuid(), "Test", jsonIn);
            await streamStore.AppendToStream(stremId, ExpectedVersion.Any, message);

            var readStreamPage = await streamStore.ReadStreamForwards(stremId, StreamVersion.Start, int.MaxValue);

            var jsonOut = await readStreamPage.Messages[0].GetJsonData();

            Assert.Equal(1, readStreamPage.Messages.Length);
            Assert.Equal(jsonIn, jsonOut);
        }
コード例 #14
0
        public static async Task Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Debug()
                         .Enrich.FromLogContext()
                         .WriteTo.Console()
                         .CreateLogger();

            using (var streamStore = new InMemoryStreamStore())
                using (var host = new WebHostBuilder()
                                  .UseKestrel()
                                  .UseStartup(new Startup(streamStore, new SqlStreamStoreMiddlewareOptions
                {
                    UseCanonicalUrls = false
                }))
                                  .UseSerilog()
                                  .UseUrls("http://localhost:5050")
                                  .Build())
                {
                    // Simulating some messages in the store here (only one stream)
                    var random   = new Random();
                    var id       = new Guid("cbf68be34d9547eb9b4a390fd2aa417b");
                    var messages = new NewStreamMessage[random.Next(1000, 2000)];
                    for (var index = 0; index < messages.Length; index++)
                    {
                        messages[index] = new NewStreamMessage(
                            Guid.NewGuid(),
                            "ItineraryPublished",
                            JsonConvert.SerializeObject(new {
                            ItineraryId = id,
                            Data        = index
                        })
                            );
                    }
                    await streamStore.AppendToStream(id.ToString("N"), ExpectedVersion.NoStream, messages);

                    // bootstrapping the server
                    var source     = new CancellationTokenSource();
                    var serverTask = host.RunAsync(source.Token);
                    // press enter to exit
                    Console.WriteLine("Running ...");
                    Console.ReadLine();
                    source.Cancel();

                    await serverTask;
                }
        }
コード例 #15
0
        public async Task CreatingStreamAndAddingMessage(int expectedVersion, int numberOfMessages)
        {
            var streamId          = "newStreamId1";
            var streamStore       = new InMemoryStreamStore();
            var newStreamMessages = new List <NewStreamMessage>();

            for (int i = 0; i < numberOfMessages; i++)
            {
                newStreamMessages.Add(new NewStreamMessage(Guid.NewGuid(), "type1", "message1", "meta1"));
            }

            var result = await streamStore.AppendToStream(new StreamId(streamId), expectedVersion,
                                                          newStreamMessages.ToArray(), CancellationToken.None);

            Assert.AreEqual(numberOfMessages - 1, result.CurrentPosition);
            Assert.AreEqual(numberOfMessages - 1, result.CurrentVersion);
        }
コード例 #16
0
        public void CreatingStreamAndAddingMessageSpecifyingWrongVersion(int expectedVersion)
        {
            var streamId          = "newStreamId1";
            var streamStore       = new InMemoryStreamStore();
            var newStreamMessages = new List <NewStreamMessage>();

            for (int i = 0; i < 1; i++)
            {
                newStreamMessages.Add(new NewStreamMessage(Guid.NewGuid(), "type1", "message1", "meta1"));
            }

            Assert.ThrowsAsync <WrongExpectedVersionException>(async() =>
            {
                await streamStore.AppendToStream(new StreamId(streamId), expectedVersion,
                                                 newStreamMessages.ToArray(), CancellationToken.None);
            });
        }
コード例 #17
0
ファイル: Usage.cs プロジェクト: mallickhruday/Projac
        public async Task ShowWithStream()
        {
            //setup a projection schema (one of many ways)
            var projector = new AsyncSqlProjector(
                Resolve.WhenEqualToHandlerMessageType(new PortfolioProjection()),
                new TransactionalSqlCommandExecutor(
                    new ConnectionStringSettings(
                        "projac",
                        @"Data Source=(localdb)\ProjectsV12;Initial Catalog=ProjacUsage;Integrated Security=SSPI;",
                        "System.Data.SqlClient"),
                    IsolationLevel.ReadCommitted));
            await projector.ProjectAsync(new object[] { new DropSchema(), new CreateSchema() });

            //setup a memory eventstore
            var store = new InMemoryStreamStore();

            //setup a sample stream (using some sample events)
            var portfolioId = Guid.NewGuid();
            var events      = new object[]
            {
                new PortfolioAdded {
                    Id = portfolioId, Name = "My Portfolio"
                },
                new PortfolioRenamed {
                    Id = portfolioId, Name = "Your Portfolio"
                },
                new PortfolioRemoved {
                    Id = portfolioId
                }
            };
            var stream = string.Format("portfolio-{0}", portfolioId.ToString("N"));
            await store.AppendToStream(
                stream,
                ExpectedVersion.Any,
                events
                .Select(@event => new NewStreamMessage(
                            Guid.NewGuid(),
                            @event.GetType().FullName,
                            JsonConvert.SerializeObject(@event)))
                .ToArray());

            //project the sample stream (until end of stream)
            var result =
                await store.ReadStreamForwards(stream, StreamVersion.Start, 1, true);

            foreach (var rawMessage in result.Messages)
            {
                var @event = JsonConvert.DeserializeObject(
                    await rawMessage.GetJsonData(),
                    Type.GetType(rawMessage.Type, true));

                await projector.ProjectAsync(@event);
            }

            while (!result.IsEnd)
            {
                result =
                    await store.ReadStreamForwards(stream, result.NextStreamVersion, 1, true);

                foreach (var rawMessage in result.Messages)
                {
                    var @event = JsonConvert.DeserializeObject(
                        await rawMessage.GetJsonData(),
                        Type.GetType(rawMessage.Type, true));

                    await projector.ProjectAsync(@event);
                }
            }
        }