public void GivenStreamOfEvents_WhenAggregateStreamIsCalled_ThenChangesAreAppliedProperly() { var streamId = EventStore.StartStream <TaskList>(); //1. First Task Was Created var task1Id = Guid.NewGuid(); EventStore.Append(streamId, new TaskCreated { TaskId = task1Id, Description = "Description" }); Session.SaveChanges(); var taskList = EventStore.AggregateStream <TaskList>(streamId); taskList.List.Should().Have.Count.EqualTo(1); taskList.List.Single().TaskId.Should().Be.EqualTo(task1Id); taskList.List.Single().Description.Should().Be.EqualTo("Description"); //2. First Task Description Was Changed EventStore.Append(streamId, new TaskUpdated { TaskId = task1Id, Description = "New Description" }); Session.SaveChanges(); taskList = EventStore.AggregateStream <TaskList>(streamId); taskList.List.Should().Have.Count.EqualTo(1); taskList.List.Single().TaskId.Should().Be.EqualTo(task1Id); taskList.List.Single().Description.Should().Be.EqualTo("New Description"); //3. Two Other tasks were added EventStore.Append(streamId, new TaskCreated { TaskId = Guid.NewGuid(), Description = "Description2" }, new TaskCreated { TaskId = Guid.NewGuid(), Description = "Description3" }); Session.SaveChanges(); taskList = EventStore.AggregateStream <TaskList>(streamId); taskList.List.Should().Have.Count.EqualTo(3); taskList.List.Select(t => t.Description) .Should() .Have.SameSequenceAs("New Description", "Description2", "Description3"); //4. First task was removed EventStore.Append(streamId, new TaskRemoved { TaskId = task1Id }); Session.SaveChanges(); taskList = EventStore.AggregateStream <TaskList>(streamId); taskList.List.Should().Have.Count.EqualTo(2); taskList.List.Select(t => t.Description) .Should() .Have.SameSequenceAs("Description2", "Description3"); }
public void GivenAggregateWithCompositeId_WhenAppendedEvent_LiveAndInlineAggregationWorks() { var seatId = new SeatId(Guid.NewGuid()); var customerId = new CustomerId(Guid.NewGuid()); var reservation = Reservation.CreateTentative(seatId, customerId); var @event = reservation.DequeueUncommittedEvents().Single(); //1. Create events EventStore.Append(reservation.AggregateId, @event); Session.SaveChanges(); //2. Get live aggregation var issuesListFromLiveAggregation = EventStore.AggregateStream <Reservation>(reservation.AggregateId); //3. Get inline aggregation var issuesListFromInlineAggregation = Session.Load <Reservation>(reservation.AggregateId); //4. Get inline aggregation through linq var reservationId = reservation.Id; var issuesListFromInlineAggregationFromLinq = Session.Query <Reservation>().SingleOrDefault(r => r.Id.Value == reservationId.Value); var issuesListFromInlineAggregationFromLinqWithAggregateId = Session.Query <Reservation>().SingleOrDefault(r => r.AggregateId == reservationId.Value); issuesListFromLiveAggregation.Should().NotBeNull(); issuesListFromInlineAggregation.Should().NotBeNull(); issuesListFromInlineAggregationFromLinq.Should().NotBeNull(); issuesListFromInlineAggregationFromLinqWithAggregateId.Should().NotBeNull(); issuesListFromLiveAggregation !.AggregateId.Should().Be(reservationId.Value); issuesListFromLiveAggregation !.AggregateId.Should().Be(reservationId.Value); issuesListFromInlineAggregationFromLinq !.AggregateId.Should().Be(reservationId.Value); issuesListFromInlineAggregationFromLinqWithAggregateId !.AggregateId.Should().Be(reservationId.Value); }
static void Save(ShoppingCart shoppingCart, EventStore eventStore) { var eventsToStore = shoppingCart.DequeueUncommittedEvents().ToList(); eventStore.Append(eventsToStore); eventStore.Save(); }
public async Task ReturnAllEventsInThePersistence() { const string streamName = "streamName"; var underTest = new EventStore(_persistence); await underTest.Append(streamName, EventStore.StreamPositions.Any, new byte[0], new byte[0]); await underTest.Append(streamName, EventStore.StreamPositions.Any, new byte[0], new byte[0]); await underTest.Append(streamName, EventStore.StreamPositions.Any, new byte[0], new byte[0]); var events = _persistence.GetAllEvents(); var total = await events.CountAsync(); Assert.Equal(3, total); }
public void GivenStreamOfEvents_WhenAggregateStreamIsCalled_ThenChangesAreAppliedProperly() { var streamId = Guid.NewGuid(); //1. First Issue Was Created var issue1Id = Guid.NewGuid(); EventStore.Append(streamId, new IssueCreated { IssueId = issue1Id, Description = "Description" }); Session.SaveChanges(); var issuesList = EventStore.AggregateStream <IssuesList>(streamId); issuesList.List.Should().Have.Count.EqualTo(1); issuesList.List.Single().IssueId.Should().Be.EqualTo(issue1Id); issuesList.List.Single().Description.Should().Be.EqualTo("Description"); //2. First Issue Description Was Changed EventStore.Append(streamId, new IssueUpdated { IssueId = issue1Id, Description = "New Description" }); Session.SaveChanges(); issuesList = EventStore.AggregateStream <IssuesList>(streamId); issuesList.List.Should().Have.Count.EqualTo(1); issuesList.List.Single().IssueId.Should().Be.EqualTo(issue1Id); issuesList.List.Single().Description.Should().Be.EqualTo("New Description"); //3. Two Other tasks were added EventStore.Append(streamId, new IssueCreated { IssueId = Guid.NewGuid(), Description = "Description2" }, new IssueCreated { IssueId = Guid.NewGuid(), Description = "Description3" }); Session.SaveChanges(); issuesList = EventStore.AggregateStream <IssuesList>(streamId); issuesList.List.Should().Have.Count.EqualTo(3); issuesList.List.Select(t => t.Description) .Should() .Have.SameSequenceAs("New Description", "Description2", "Description3"); //4. First issue was removed EventStore.Append(streamId, new IssueRemoved { IssueId = issue1Id }); Session.SaveChanges(); issuesList = EventStore.AggregateStream <IssuesList>(streamId); issuesList.List.Should().Have.Count.EqualTo(2); issuesList.List.Select(t => t.Description) .Should() .Have.SameSequenceAs("Description2", "Description3"); }
public async Task WriteEventWhenStreamNotCreatedAndPositionIsCreate() { var eventPersistence = _persistence; var underTest = new EventStore(eventPersistence); var result = await underTest.Append("streamName", EventStore.StreamPositions.Create, new byte[0], new byte[0]); Assert.Equal(1, result.NextPosition); }
public async Task ThrowUnexpectedPositionWhenStreamExistsAndPositionWrongOnAppend() { const string streamName = "streamName"; await _persistence.AppendEvent(new IEventPersistence.Event(streamName, 0, new byte[0], new byte[0])); var underTest = new EventStore(_persistence); await Assert.ThrowsAsync <UnexpectedStreamPositionException>(() => underTest.Append(streamName, 2, new byte[0], new byte[0])); }
public async Task ReturnEventsByStream() { var underTest = new EventStore(_persistence); await underTest.Append("streamName", EventStore.StreamPositions.Any, new byte[0], new byte[0]); await underTest.Append("streamName2", EventStore.StreamPositions.Any, new byte[0], new byte[0]); await underTest.Append("streamName2", EventStore.StreamPositions.Any, new byte[0], new byte[0]); var events = underTest.ReadStreamForward("streamName", 0); var total = await events.CountAsync(); Assert.Equal(1, total); events = underTest.ReadStreamForward("streamName2", 0); total = await events.CountAsync(); Assert.Equal(2, total); }
public async Task WriteEventWhenExpectedPositionIsAnyOnAppend() { var eventPersistence = _persistence; var underTest = new EventStore(eventPersistence); var result = await underTest.Append("streamName", EventStore.StreamPositions.Any, new byte[0], new byte[0]); Assert.Equal(0, result.NextPosition); var eventsTotal = await _persistence.GetAllEvents().CountAsync(); Assert.Equal(1, eventsTotal); }
public void GivenSetOfEvents_WithFetchEventsFromDifferentVersionNumber_ThenProperSetsAreLoaded() { //Given var streamId = Guid.NewGuid(); var taskId = Guid.NewGuid(); //When EventStore.Append(streamId, new TaskCreated { TaskId = taskId, Description = "Initial Name" }); Session.SaveChanges(); EventStore.Append(streamId, new TaskUpdated { TaskId = taskId, Description = "Updated name" }); Session.SaveChanges(); EventStore.Append(streamId, new TaskUpdated { TaskId = taskId, Description = "Updated again name" }, new TaskUpdated { TaskId = taskId, Description = "Updated again and again name" }); Session.SaveChanges(); //Then //version after create var events = EventStore.FetchStream(streamId, 1); events.Count.Should().Be.EqualTo(1); //version after first update events = EventStore.FetchStream(streamId, 2); events.Count.Should().Be.EqualTo(2); //even though 3 and 4 updates were append at the same time version is incremented for both of them events = EventStore.FetchStream(streamId, 3); events.Count.Should().Be.EqualTo(3); events = EventStore.FetchStream(streamId, 4); events.Count.Should().Be.EqualTo(4); //fetching with version equal to 0 returns the most recent state events = EventStore.FetchStream(streamId, 0); events.Count.Should().Be.EqualTo(4); //providing bigger version than current doesn't throws exception - returns most recent state events = EventStore.FetchStream(streamId, 100); events.Count.Should().Be.EqualTo(4); }
public void GivenOneEvent_WhenEventsArePublishedWithStreamId_ThenEventsAreSavedWithoutErrorAndStreamIsStarted() { var @event = new IssueCreated(Guid.NewGuid(), "Description"); var streamId = Guid.NewGuid(); EventStore.Append(streamId, @event); Session.SaveChanges(); var streamState = EventStore.FetchStreamState(streamId); streamState.Should().Not.Be.Null(); streamState.Version.Should().Be.EqualTo(1); }
public async Task OnGetAsync(int guest) { Bill = _events .Project( default(BillViewModel), BillViewModel.OpenBillFor(guest) ); var paymentMethods = await _billingClient.GetFromJsonAsync <PaymentMethod[]>($"payment/{Bill.Bill}"); _events.Append(new PaymentMethodsSupported(guest, Bill.Bill, paymentMethods)); SupportedPaymentMethods = paymentMethods .Select(x => new SelectListItem { Text = x.ToString(), Value = x.ToString() }) .ToList(); Command = new PaymentCommand { Guest = guest, Bill = Bill.Bill }; }
public void GivenExistingStreamWithOneEvent_WhenEventIsAppended_ThenItLoadsTwoEvents() { //Given var streamId = GetExistingStreamId(); //When EventStore.Append(streamId, new IssueUpdated(issueId, "New Description")); Session.SaveChanges(); //Then var events = EventStore.FetchStream(streamId); events.Count.Should().Be.EqualTo(2); events.Last().Version.Should().Be.EqualTo(2); }
public void GivenSetOfEvents_WithFetchEventsFromDifferentTimes_ThenProperSetsAreLoaded() { //Given var streamId = Guid.NewGuid(); var taskId = Guid.NewGuid(); //When var beforeCreateTimestamp = DateTime.UtcNow; EventStore.Append(streamId, new TaskCreated { TaskId = taskId, Description = "Initial Name" }); Session.SaveChanges(); var createTimestamp = DateTime.UtcNow; EventStore.Append(streamId, new TaskUpdated { TaskId = taskId, Description = "Updated name" }); Session.SaveChanges(); var firstUpdateTimestamp = DateTime.UtcNow; EventStore.Append(streamId, new TaskUpdated { TaskId = taskId, Description = "Updated again name" }, new TaskUpdated { TaskId = taskId, Description = "Updated again and again name" }); Session.SaveChanges(); var secondUpdateTimestamp = DateTime.UtcNow; //Then var events = EventStore.FetchStream(streamId, timestamp: beforeCreateTimestamp); events.Count.Should().Be.EqualTo(0); events = EventStore.FetchStream(streamId, timestamp: createTimestamp); events.Count.Should().Be.EqualTo(1); events = EventStore.FetchStream(streamId, timestamp: firstUpdateTimestamp); events.Count.Should().Be.EqualTo(2); events = EventStore.FetchStream(streamId, timestamp: secondUpdateTimestamp); events.Count.Should().Be.EqualTo(4); }
public ComponentRegistrarBuilder RegisterEventsStorage <TAppendOnlyStore>(string connectionName = "EventStore") where TAppendOnlyStore : class, IAppendOnlyStore { if (!string.IsNullOrWhiteSpace(connectionName)) { var connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString; _container.Register( Component.For <IAppendOnlyStore>() .ImplementedBy(typeof(TAppendOnlyStore)) .Named(typeof(TAppendOnlyStore).Name) .DependsOn( Property.ForKey("connectionString") .Eq(connectionString ?? typeof(TAppendOnlyStore).Name)).IsDefault() .LifeStyle.Transient); _container.Register( Component.For(typeof(IEventStore)) .ImplementedBy(typeof(EventStore)) .Named("eventStore").LifestyleTransient()); } else { _container.Register( Component.For <IAppendOnlyStore>() .ImplementedBy(typeof(TAppendOnlyStore)) .Named(typeof(TAppendOnlyStore).Name) .LifeStyle.Singleton); _container.Register( Component.For(typeof(IEventStore)) .ImplementedBy(typeof(EventStore)) .Named("eventStore").LifestyleTransient()); } EventStore = _container.Resolve <IEventStore>(); DomainEventPublisher.Instance.Subscribe(domainEvent => EventStore.Append(domainEvent)); return(this); }