public async Task Handle(MembershipPointsEarnedEvent notification, CancellationToken cancellationToken) { var membership = await _readModelDbContext.Memberships .Include(m => m.Points) .FirstOrDefaultAsync(m => m.Id == notification.Id); // this is require, as otherwise, the place where it save to the read mokdel will throw some exceptions _readModelDbContext.Entry(membership).State = EntityState.Detached; var newPoints = membership.TotalPoints; var newPointsPer100 = (int)(newPoints / 100); var previousPoints = membership.TotalPoints - notification.Amount; var previousPointsPer100 = (int)(previousPoints / 100); var rewardPointsEarned = newPointsPer100 - previousPointsPer100; if (rewardPointsEarned > 0) { var rewardType = (rewardPointsEarned == 1) ? RewardType.GiftVoucher : RewardType.FreeMeal; var entity = new Reward(membership.CustomerId, rewardType); await _simpleEventStoreDbContext.SavePendingEventsAsync(entity.PendingEvents, 1, "Sample"); await _eventBusService.Publish(entity.PendingEvents); } }
public async Task Insertion_of_new_events_during_catchup_does_not_interrupt_catchup() { var barrier = new Barrier(2); // preload some events for the catchup. replay will hit the barrier on the last one. var order = new Order(); Action addEvent = () => order.Apply(new AddItem { Quantity = 1, ProductName = "Penny candy", Price = .01m }); Enumerable.Range(1, 100).ForEach(_ => addEvent()); var repository = new SqlEventSourcedRepository <Order>(new FakeEventBus()); await repository.Save(order); // queue the catchup on a background task #pragma warning disable 4014 // don't await Task.Run(() => #pragma warning restore 4014 { var projector = new Projector1 { OnUpdate = (work, e) => { if (e.SequenceNumber == 10) { Console.WriteLine("pausing read model catchup"); barrier.SignalAndWait(MaxWaitTime); //1 barrier.SignalAndWait(MaxWaitTime); //2 Console.WriteLine("resuming read model catchup"); } } }; using (var db = new EventStoreDbContext()) using (var catchup = CreateReadModelCatchup(projector)) { var events = db.Events.Where(e => e.Id > HighestEventId); Console.WriteLine(string.Format("starting read model catchup for {0} events", events.Count())); catchup.Run().Wait(); Console.WriteLine("done with read model catchup"); barrier.SignalAndWait(MaxWaitTime); //3 } }); Console.WriteLine("queued read model catchup task"); barrier.SignalAndWait(MaxWaitTime); //1 new EventStoreDbContext().DisposeAfter(c => { Console.WriteLine("adding one more event, bypassing read model tracking"); c.Events.Add(new Order.ItemAdded { AggregateId = Guid.NewGuid(), SequenceNumber = 1 }.ToStorableEvent()); c.SaveChanges(); Console.WriteLine("done adding one more event"); }); barrier.SignalAndWait(MaxWaitTime); //2 barrier.SignalAndWait(MaxWaitTime); //3 // check that everything worked: var projector2 = new Projector1(); var projectorName = ReadModelInfo.NameForProjector(projector2); using (var readModels = new ReadModelDbContext()) { var readModelInfo = readModels.Set <ReadModelInfo>().Single(i => i.Name == projectorName); readModelInfo.CurrentAsOfEventId.Should().Be(HighestEventId + 101); using (var catchup = CreateReadModelCatchup(projector2)) { await catchup.Run(); } readModels.Entry(readModelInfo).Reload(); readModelInfo.CurrentAsOfEventId.Should().Be(HighestEventId + 102); } }