public async Task HandleAsync_QueryModelDoesntExist_CreatesNew() { var command = Fixtures.Pipelines.FakeCreateCommand(); var @event = Fixtures.Pipelines.FakeCreatedIntegrationEvent(command); var notification = new IntegrationEventNotification <FakeCreatedIntegrationEvent>(@event); // No query model in storage. (await storage.FindAsync(@event.SnapshotId.EntryId, @event.SnapshotId.EntryVersion)).Should().BeNull(); await handler.Handle(notification, CancellationToken.None); // Query model is created. var queryModel = await storage.GetAsync(@event.SnapshotId.EntryId, @event.SnapshotId.EntryVersion); queryModel.Should().NotBeNull(); queryModel.AppliedEvent.Should().BeEquivalentTo(new AppliedEvent { Id = @event.Id, Created = @event.Created }); // Query model updated notification is fired. var expectedSignal = QueryModelChangedSignal.CreateFromSource( @event, queryModel.Id, queryModel.Version, queryModel.GetType(), QueryModelChangeOperation.Create); mediator.PublishedNotifications.Single().Should().BeOfType <QueryModelChangedNotification>() .Which.Signal.Should().BeEquivalentTo(expectedSignal, options => options.ForSignal()); }
public async Task HandleCreate_QueryModelExist_UpdatesExisting() { var command = Fixtures.Pipelines.FakeCreateCommand(); // Creates query model. var createEvent = Fixtures.Pipelines.FakeCreatedIntegrationEvent(command); var createNotification = new IntegrationEventNotification <FakeCreatedIntegrationEvent>(createEvent); await handler.Handle(createNotification, CancellationToken.None); // Updates query model. var updateEvent = Fixtures.Pipelines.FakeCreatedIntegrationEvent(command); var updateNotification = new IntegrationEventNotification <FakeCreatedIntegrationEvent>(updateEvent); await handler.Handle(updateNotification, CancellationToken.None); // Get existing query model. var queryModel = await storage.GetAsync(createEvent.SnapshotId.EntryId); queryModel.Should().NotBeNull(); queryModel.AppliedEvent.Should().BeEquivalentTo(new AppliedEvent { Id = updateEvent.Id, Created = updateEvent.Created }); // Query model updated notification is fired. var expectedSignal = QueryModelChangedSignal.CreateFromSource( updateEvent, queryModel.Id, queryModel.GetType(), QueryModelChangeOperation.Update); mediator.PublishedNotifications[^ 1].Should().BeOfType <QueryModelChangedNotification>()
public QueryModelChangedSignal FakeQueryModelDeletedSignal <TQueryModel>(FakeDeletedIntegrationEvent integrationEvent) { return(QueryModelChangedSignal.CreateFromSource( integrationEvent, integrationEvent.AggregateRootId, 0, typeof(TQueryModel), QueryModelChangeOperation.Delete)); }
public void CreateFromSource2_Always_CopiesMessageCorrelationData() { var integrationEvent = Fixtures.Pipelines.FakeCreatedIntegrationEvent(); var signal = QueryModelChangedSignal.CreateFromSource( integrationEvent, Unified.NewCode(), typeof(int), FixtureUtils.FromEnum <QueryModelChangeOperation>()); signal.Should().BeEquivalentTo(integrationEvent, options => options.ForMessage()); }
/// <summary> /// Deletes query model. /// </summary> /// <param name="notification">Event notification.</param> /// <param name="getId">Returns query model id from provided event.</param> /// <typeparam name="TEvent">Event type.</typeparam> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> protected async Task DeleteAsync <TEvent>(IntegrationEventNotification <TEvent> notification, Func <TEvent, string> getId) where TEvent : IIntegrationEvent { var @event = notification.IntegrationEvent; var id = getId(@event); await Writer.DeleteAsync(id); var signal = QueryModelChangedSignal.CreateFromSource(@event, id, typeof(TQueryModel), QueryModelChangeOperation.Delete); await Mediator.Publish(new QueryModelChangedNotification(signal) { IsReplay = @event.IsReplay, IsPrivate = IsPrivateQueryModel }); }
/// <summary> /// Updates query model using async setup. /// </summary> /// <param name="notification">Event notification.</param> /// <param name="getId">Returns query model id from provided event.</param> /// <param name="setup">Update query model using async setup.</param> /// <typeparam name="TEvent">Event type.</typeparam> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> protected async Task HandleAsync <TEvent>( IntegrationEventNotification <TEvent> notification, Func <TEvent, string> getId, Func <TEvent, TQueryModel, Task> setup) where TEvent : IIntegrationEvent { var @event = notification.IntegrationEvent; var id = getId(@event); // Find query model. var queryModel = await Reader.FindAsync(id) ?? new TQueryModel(); var isNew = string.IsNullOrWhiteSpace(queryModel.AppliedEvent.Id); if (queryModel.AppliedEvent.Created >= @event.Created) { await Mediator.Publish(new EventAlreadyAppliedNotification(@event, queryModel)); return; } // Update query model. queryModel.Id = id; queryModel.AppliedEvent = new AppliedEvent { Id = @event.Id, Created = @event.Created }; await setup(@event, queryModel); // Save updated query model. var saved = isNew ? await Writer.CreateAsync(queryModel) : await Writer.ReplaceAsync(queryModel); // Publish signal. var operation = isNew ? QueryModelChangeOperation.Create : QueryModelChangeOperation.Update; var signal = QueryModelChangedSignal.CreateFromSource(@event, saved.Id, saved.GetType(), operation); await Mediator.Publish(new QueryModelChangedNotification(signal) { IsReplay = @event.IsReplay, IsPrivate = IsPrivateQueryModel }); }
/// <summary> /// Updates query model. /// </summary> /// <param name="notification">Event notification.</param> /// <param name="getSnapshotId">Returns snapshot id from provided event.</param> /// <param name="setup">Update query model.</param> /// <typeparam name="TEvent">Event type.</typeparam> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> protected async Task HandleAsync <TEvent>( IntegrationEventNotification <TEvent> notification, Func <TEvent, SnapshotId> getSnapshotId, Action <TEvent, TQueryModel> setup) where TEvent : IIntegrationEvent { var @event = notification.IntegrationEvent; var snapshotId = getSnapshotId(@event); // Find query model. var model = await Reader.FindLatestAsync(snapshotId.EntryId) ?? new TQueryModel(); if (model.AppliedEvent.Created >= @event.Created) { await Mediator.Publish(new EventAlreadyAppliedNotification(@event, model)); return; } // Update query model. model.Id = snapshotId.EntryId; model.Version = snapshotId.EntryVersion; model.AppliedEvent = new AppliedEvent { Id = @event.Id, Created = @event.Created }; setup(@event, model); // Save updated query model. var created = await Writer.CreateAsync(model); var signal = QueryModelChangedSignal.CreateFromSource(@event, created.Id, created.Version, created.GetType(), QueryModelChangeOperation.Create); await Mediator.Publish(new QueryModelChangedNotification(signal) { IsReplay = @event.IsReplay, IsPrivate = IsPrivateQueryModel }); }