public async Task Report_projections_can_be_created_using_anonymous_projectors_over_multiple_event_types() { var projector = Projector.Combine( Projector.CreateFor <Placed>(e => { using (var db1 = new ReadModelDbContext()) { db1.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count++; db1.SaveChanges(); } }), Projector.CreateFor <Cancelled>(e => { using (var db2 = new ReadModelDbContext()) { db2.OrderTallyByStatus(OrderTally.OrderStatus.Canceled).Count++; db2.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count--; db2.SaveChanges(); } }), Projector.CreateFor <Delivered>(e => { using (var db3 = new ReadModelDbContext()) { db3.OrderTallyByStatus(OrderTally.OrderStatus.Delivered).Count++; db3.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count--; db3.SaveChanges(); } })).Named("Order status report"); Events.Write(20, _ => new Order.Cancelled()); Events.Write(20, _ => new Order.Delivered()); Events.Write(50, _ => new Order.Placed()); using (var catchup = CreateReadModelCatchup(projector)) { await catchup.Run(); } using (var db = new ReadModelDbContext()) { db.Set <OrderTally>() .Single(t => t.Status == "Canceled") .Count .Should() .Be(20); db.Set <OrderTally>() .Single(t => t.Status == "Delivered") .Count .Should() .Be(20); db.Set <OrderTally>() .Single(t => t.Status == "Pending") .Count .Should() .Be(10); } }
public CustomerDomainService( ReadModelDbContext readModelDbContext, SimpleEventStoreDbContext eventStoreDbContext, IEventBusService eventBusService) { _readModelDbContext = readModelDbContext; _eventStoreDbContext = eventStoreDbContext; _eventBusService = eventBusService; }
public EventDispatcher(ReadModelDbContext dbContext, ILogger logger) { _dbContext = dbContext; _logger = logger; _resolver = new EventHandlerResolver(); RegisterHandlers(); }
public RewardsEventHandlers( ReadModelDbContext readModelDbContext, SimpleEventStoreDbContext simpleEventStoreDbContext, IEventBusService eventBusService) { _readModelDbContext = readModelDbContext; _simpleEventStoreDbContext = simpleEventStoreDbContext; _eventBusService = eventBusService; }
public Task Handle(PlayerInventoryChangedEvent evnt) { // TODO: Make fully async and using proper DI using (var dbContext = ReadModelDbContext.CreateContext(_configuration)) { var entityRepository = new EntityRepository(dbContext); entityRepository.Enrich(evnt.InventoryChange); } return(Task.CompletedTask); }
public EventStoreDbTest() { Logging.Configure(); SetConnectionStrings(); Command <Order> .AuthorizeDefault = (order, command) => true; Command <CustomerAccount> .AuthorizeDefault = (order, command) => true; lock (lockObj) { if (databasesInitialized) { return; } // TODO: (EventStoreDbTest) figure out a db cleanup story //#if !DEBUG // new EventStoreDbContext().Database.Delete(); // new OtherEventStoreDbContext().Database.Delete(); // new ReadModelDbContext().Database.Delete(); // new ReadModels1DbContext().Database.Delete(); // new ReadModels2DbContext().Database.Delete(); // new CommandSchedulerDbContext().Database.Delete(); //#endif using (var eventStore = new EventStoreDbContext()) { new EventStoreDatabaseInitializer <EventStoreDbContext>().InitializeDatabase(eventStore); } using (var db = new CommandSchedulerDbContext()) { new CommandSchedulerDatabaseInitializer().InitializeDatabase(db); } using (var eventStore = new OtherEventStoreDbContext()) { new EventStoreDatabaseInitializer <OtherEventStoreDbContext>().InitializeDatabase(eventStore); } using (var db = new ReadModelDbContext()) { new ReadModelDatabaseInitializer <ReadModelDbContext>().InitializeDatabase(db); } using (var db = new ReadModels1DbContext()) { new ReadModelDatabaseInitializer <ReadModels1DbContext>().InitializeDatabase(db); } using (var db = new ReadModels2DbContext()) { new ReadModelDatabaseInitializer <ReadModels2DbContext>().InitializeDatabase(db); } databasesInitialized = true; } }
private void SetupReadModelDbContext() { var mongoDbConnectionString = TestContextUtils.GetParameterOrDefault("mongodb-connection-string", "mongodb://localhost:27017"); var dbContext = new ReadModelDbContext(new MongoDbSettings() { ConnectionString = mongoDbConnectionString, DatabaseName = "appDb" }, new CategoryBuilder(CategoryTreeService)); DbContext = dbContext; }
public override void SetUp() { Console.WriteLine("ReportingProjectorTests.SetUp"); base.SetUp(); // reset order tallies using (var db = new ReadModelDbContext()) { var tallies = db.Set <OrderTally>(); tallies.ToArray().ForEach(t => tallies.Remove(t)); db.SaveChanges(); } }
public OrderTallyProjector() { On <Placed>(e => { using (var db = new ReadModelDbContext()) { db.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count++; db.SaveChanges(); } }); On <Cancelled>(e => { using (var db = new ReadModelDbContext()) { db.OrderTallyByStatus(OrderTally.OrderStatus.Canceled).Count++; db.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count--; db.SaveChanges(); } }); On <Delivered>(e => { using (var db = new ReadModelDbContext()) { db.OrderTallyByStatus(OrderTally.OrderStatus.Delivered).Count++; db.OrderTallyByStatus(OrderTally.OrderStatus.Pending).Count--; db.SaveChanges(); } }); On("Order.Fulfilled", e => { using (var db = new ReadModelDbContext()) { db.OrderTallyByStatus(OrderTally.OrderStatus.Fulfilled).Count++; db.SaveChanges(); } }); On("Order.Misdelivered", e => { using (var db = new ReadModelDbContext()) { db.OrderTallyByStatus(OrderTally.OrderStatus.Misdelivered).Count++; db.SaveChanges(); } }); }
private void ResetReadModelInfo() { using (var db = new ReadModelDbContext()) { foreach (var info in db.Set <ReadModelInfo>()) { info.InitialCatchupStartTime = null; info.InitialCatchupEndTime = null; info.BatchRemainingEvents = 0; info.BatchTotalEvents = 0; info.BatchStartTime = null; } db.SaveChanges(); } }
public async Task HandleEvent <TEvent>(TEvent evnt) where TEvent : IEvent { using (var dbContext = ReadModelDbContext.CreateContext(_configuration)) { var dispatcher = new EventDispatcher(dbContext, _logger); await dispatcher.Handle(evnt); UpdateState(dbContext, evnt); try { await dbContext.SaveChangesAsync(); } catch (Exception e) { _logger.Error(e, $"Could not commit changes from dispatcher!"); } } }
public async Task When_not_using_Update_then_failed_writes_do_not_interrupt_catchup() { // arrange // preload some events for the catchup. replay will hit the barrier on the last one. var order = new Order(); var productName = Any.Paragraph(3); Action addEvent = () => order.Apply(new AddItem { Quantity = 1, ProductName = productName, Price = .01m }); Enumerable.Range(1, 30).ForEach(_ => addEvent()); var repository = new SqlEventSourcedRepository <Order>(new FakeEventBus()); await repository.Save(order); var count = 0; var projector = new Projector1 { OnUpdate = (work, e) => { using (var db = new ReadModelDbContext()) { // throw one exception in the middle if (count++ == 15) { throw new Exception("drat!"); } db.SaveChanges(); } } }; // act using (var catchup = CreateReadModelCatchup(projector)) { await catchup.Run(); } // assert count.Should().Be(30); }
public void SetUp() { _categoryTreeService = TestDepedencies.Instance.Value.CategoryTreeService; _dbContext = TestDepedencies.Instance.Value.DbContext; var testCategoryTree = _categoryTreeService.GetCategoriesTree(); var testCategory = new Category(testCategoryTree.SubCategories[0].CategoryName, 0); testCategory.SubCategory = new Category(testCategoryTree.SubCategories[0].SubCategories[0].CategoryName, 1); testCategory.SubCategory.SubCategory = new Category(testCategoryTree.SubCategories[0].SubCategories[0].SubCategories[0].CategoryName, 2); stubAuction = new AuctionRead() { ActualPrice = 20, AuctionId = Guid.NewGuid().ToString(), BuyNowPrice = 21, StartDate = DateTime.UtcNow.AddMinutes(12), EndDate = DateTime.UtcNow.AddDays(1), Category = testCategory, Product = new Product("test product name", "example description", Condition.New) }; }
public void ConfigureServices(IServiceCollection services) { services.AddSingleton(_configuration.Bind <ConfigurationBase>()); services.AddSingleton(_configuration); services.AddSingleton(_logger); services.AddMvc().AddJsonOptions(opts => { opts.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); services.AddSignalR().AddJsonProtocol(opts => { opts.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); services.AddAntiforgery(); services.AddFactorinoAuthentication(_configuration); services.AddSwaggerGen(opts => { opts.SwaggerDoc("v1", new Info { Title = "Factorino API", Version = "v1" }); }); services.AddDbContext <ReadModelDbContext>(opts => { // We're disabling tracking here, because the webapp will never write to db ReadModelDbContext.ConfigureBuilder(opts, _configuration, disableTracking: true); }); services.AddScoped <IPlayerRepository, PlayerRepository>(); services.AddScoped <IFactoryRepository, FactoryRepository>(); services.AddScoped <DeedRepository, DeedRepository>(); services.AddScoped <ICorporationRepository, CorporationRepository>(); services.AddScoped <IEntityRepository, EntityRepository>(); services.AddScoped <IMarketRepository, MarketRepository>(); services.AddScoped <IShippingRepository, ShippingRepository>(); services.AddScoped <IEventStore, KafkaProducer>(); services.AddHostedService <EventStreamMediator>(); }
public async Task Events_that_cannot_be_deserialized_to_the_expected_type_are_logged_as_EventHandlingErrors() { var badEvent = new StorableEvent { Actor = Any.Email(), StreamName = typeof(Order).Name, Type = typeof(Order.ItemAdded).Name, Body = new { Price = "oops this is not a number" }.ToJson(), SequenceNumber = Any.PositiveInt(), AggregateId = Any.Guid(), UtcTime = DateTime.UtcNow }; using (var eventStore = new EventStoreDbContext()) { eventStore.Events.Add(badEvent); await eventStore.SaveChangesAsync(); } using (var catchup = CreateReadModelCatchup(new Projector1())) { await catchup.Run(); } using (var readModels = new ReadModelDbContext()) { var failure = readModels.Set <EventHandlingError>() .OrderByDescending(e => e.Id) .First(e => e.AggregateId == badEvent.AggregateId); failure.Error.Should().Contain("JsonReaderException"); failure.SerializedEvent.Should().Contain(badEvent.Body); failure.Actor.Should().Be(badEvent.Actor); failure.OriginalId.Should().Be(badEvent.Id); failure.AggregateId.Should().Be(badEvent.AggregateId); failure.SequenceNumber.Should().Be(badEvent.SequenceNumber); failure.StreamName.Should().Be(badEvent.StreamName); failure.EventTypeName.Should().Be(badEvent.Type); } }
public static OrderTally OrderTallyByStatus( this ReadModelDbContext db, OrderTally.OrderStatus status) { var statusString = status.ToString(); var dbSet = db.Set <OrderTally>(); return(dbSet .SingleOrDefault(o => o.Status == statusString) .IfNotNull() .Else(() => { var tally = new OrderTally { Status = statusString }; dbSet.Add(tally); return tally; })); }
public static UserRead AddCredits <T>(ReadModelDbContext dbContext, IAppEvent <T> appEvent, decimal creditsCount, UserIdentity user, IRequestStatusService requestStatusService) where T : Event { var filter = Builders <UserRead> .Filter.Eq(read => read.UserIdentity.UserId, user.UserId.ToString()); var update = Builders <UserRead> .Update.Inc(read => read.Credits, creditsCount); var userRead = dbContext.UsersReadModel.FindOneAndUpdate(filter, update); if (userRead == null) { requestStatusService.TrySendRequestFailureToUser(appEvent, user); throw new QueryException("Null userReadModel"); } requestStatusService.TrySendReqestCompletionToUser(appEvent, user, new Dictionary <string, object>() { { "ammount", creditsCount } }); return(userRead); }
private void UpdateState(ReadModelDbContext dbContext, IEvent evnt) { var existingState = dbContext.ConsumerStates.FirstOrDefault(s => s.GroupId == _configurationModel.Kafka.GroupId && s.Topic == evnt.GetMetadata().Topic&& s.Partition == evnt.GetMetadata().Partition); if (existingState != null) { // We already have a state; update existingState.Offset = evnt.GetMetadata().Offset; } else { // We need to start tracking this state dbContext.ConsumerStates.Add(new ConsumerState { GroupId = _configurationModel.Kafka.GroupId, Topic = evnt.GetMetadata().Topic, Partition = evnt.GetMetadata().Partition, Offset = evnt.GetMetadata().Offset, }); } }
public void Run() { using (var dbContext = ReadModelDbContext.CreateContext(_configuration)) { var initialState = dbContext.ConsumerStates .Where(s => s.GroupId == _configurationModel.Kafka.GroupId) .ToList(); if (initialState.Count() > 0) { // We have already rehydrated this context; lets continue where we left off var subscriptions = initialState .Select(s => new TopicPartitionOffset(s.Topic, s.Partition, s.Offset + 1)) .ToArray(); _logger.Information($"Found existing context state, subscribing to: ${string.Join(", ", subscriptions.Select(s => s.ToString()))}"); _consumer.Subscribe(subscriptions); } else { // This context needs rehydration; start from beginning _logger.Information("No existing state found for context; rehydrating.."); _consumer.Subscribe(new TopicPartitionOffset(KafkaTopics.EVENTS, 0, 0)); } } }
public ChangeNameCustomerCommandHandler(ReadModelDbContext readModelDbContext, ICustomerDomainService service) { _readModelDbContext = readModelDbContext; _service = service; }
public TestAuctionCreatedHandler(IAppEventBuilder appEventBuilder, ReadModelDbContext dbContext, IRequestStatusService requestStatusService) : base(appEventBuilder, dbContext, requestStatusService, Mock.Of <ILogger <TestAuctionCreatedHandler> >()) { }
public AuctionCompletedHandler(IAppEventBuilder appEventBuilder, ReadModelDbContext dbContext, ILogger <AuctionCompletedHandler> logger) : base(appEventBuilder, logger) { _dbContext = dbContext; }
public FactoryEventHandler(ReadModelDbContext dbContext, ILogger logger) : base(logger) { _dbContext = dbContext; }
public EnsureConsumerConsistencyFilter(ILogger logger, ReadModelDbContext dbContext) { _logger = logger; _dbContext = dbContext; }
public KmStandViewRepository(IDesignTimeDbContextFactory <ReadModelDbContext> contextFactory) { _contextFactory = contextFactory; _context = contextFactory.CreateDbContext(Array.Empty <string>()); }
public GetAllCustomersQueryHandler(ReadModelDbContext readModelDbContext) { _readModelDbContext = readModelDbContext; }
public GetCustomerRewardsQueryHandler(ReadModelDbContext readModelDbContext) { _readModelDbContext = readModelDbContext; }
public void Projection_write_speed_without_unit_of_work() { var eventsRead = 0; var projector1 = Projector.Create<IEvent>(e => { using (var db = new ReadModelDbContext()) { db.Set<ProductInventory>().Add(new ProductInventory { ProductName = Guid.NewGuid().ToString(), QuantityInStock = Any.Int(1, 5), QuantityReserved = 0 }); db.SaveChanges(); eventsRead++; } }).Named(MethodBase.GetCurrentMethod().Name + ":projector1"); using (var catchup = new ReadModelCatchup(projector1) { StartAtEventId = startAtEventId }) { catchup.Run(); } Console.WriteLine(new { eventsRead }); // TODO: (Write_speed_without_unit_of_work) write test Assert.Fail("Test not written yet."); }
public EntityTypeReadModelRepository(ReadModelDbContext dbContext) { _dbContext = dbContext; }
public TopAuctionsByProductNameQueryHandler(ReadModelDbContext dbContext) { _dbContext = dbContext; }
public AuctionsByTagQueryHandler(ReadModelDbContext dbContext) { _dbContext = dbContext; }