Exemplo n.º 1
0
        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());
        }
Exemplo n.º 2
0
 public Task Handle(IntegrationEventNotification <FakeImmutableUpdatedIntegrationEvent> notification, CancellationToken cancellationToken)
 {
     return(HandleAsync(notification, e => e.SnapshotId, (e, qm) =>
     {
         qm.Data = e.Data;
     }));
 }
Exemplo n.º 3
0
        public async Task HandleAsync_EventAlreadyApplied_PublishesAlreadyAppliedNotification()
        {
            var command = Fixtures.Pipelines.FakeCreateCommand();
            var @event  = Fixtures.Pipelines.FakeCreatedIntegrationEvent(command);

            // Ensure query model already exist.
            var queryModel = new FakeImmutableQueryModel
            {
                Id           = @event.SnapshotId.EntryId,
                Version      = @event.SnapshotId.EntryVersion,
                AppliedEvent = new AppliedEvent {
                    Id = @event.Id, Created = @event.Created
                }
            };

            await storage.CreateAsync(queryModel);

            // Fire event again.
            var notification = new IntegrationEventNotification <FakeCreatedIntegrationEvent>(@event);

            await handler.Handle(notification, CancellationToken.None);

            // Event already applied notification is fired.
            mediator.PublishedNotifications.Single().Should().BeOfType <EventAlreadyAppliedNotification>()
            .Which.QueryModelType.Should().Be(typeof(FakeImmutableQueryModel));
        }
Exemplo n.º 4
0
 public Task Handle(IntegrationEventNotification <FakeCreatedIntegrationEvent> notification, CancellationToken cancellationToken)
 {
     return(HandleAsync(notification, e => e.Id, (e, qm) =>
     {
         qm.Data = e.Data;
     }));
 }
Exemplo n.º 5
0
        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 async Task <bool> Handle(IntegrationEventNotification <PriceCalculatedIntegrationEvent> notification, CancellationToken cancellationToken)
        {
            var command = new UpdatePriceCommand(notification.Data.OrderId, notification.Data.Total);

            var identifiedCommand = new IdentifiedCommand <UpdatePriceCommand, bool>(command, notification.Data.Id);

            return(await _mediator.Send(identifiedCommand, cancellationToken));
        }
Exemplo n.º 7
0
 /// <summary>
 /// Updates query model.
 /// </summary>
 /// <param name="notification">Event notification.</param>
 /// <param name="getId">Returns query model 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 Task HandleAsync <TEvent>(
     IntegrationEventNotification <TEvent> notification,
     Func <TEvent, string> getId,
     Action <TEvent, TQueryModel> setup)
     where TEvent : IIntegrationEvent
 {
     return(HandleAsync(notification, getId, (e, qm) =>
     {
         setup(e, qm);
         return Task.CompletedTask;
     }));
 }
Exemplo n.º 8
0
        public async Task HandleAsync_EventIsReplay_AddIsReplayToNotification()
        {
            var command = Fixtures.Pipelines.FakeCreateCommand();
            var @event  = Fixtures.Pipelines.FakeCreatedIntegrationEvent(command);

            @event.IsReplay = true;
            var notification = new IntegrationEventNotification <FakeCreatedIntegrationEvent>(@event);

            await handler.Handle(notification, CancellationToken.None);

            mediator.PublishedNotifications.Single().Should().BeOfType <QueryModelChangedNotification>()
            .Which.IsReplay.Should().BeTrue();
        }
Exemplo n.º 9
0
        /// <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
            });
        }
Exemplo n.º 10
0
        /// <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
            });
        }
Exemplo n.º 12
0
        public async Task HandleAsync_SetupQueryModelPrivacy_NotificationPrivacyIsCorrect(bool isPrivate)
        {
            // Setup query model privacy.
            handler.SetupIsPrivateQueryModel(isPrivate);

            var command      = Fixtures.Pipelines.FakeCreateCommand();
            var @event       = Fixtures.Pipelines.FakeCreatedIntegrationEvent(command);
            var notification = new IntegrationEventNotification <FakeCreatedIntegrationEvent>(@event);

            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 privacy is correct.
            mediator.PublishedNotifications.Single().Should().BeOfType <QueryModelChangedNotification>()
            .Which.IsPrivate.Should().Be(isPrivate);
        }
 public Task Handle(IntegrationEventNotification <FakeDispatcherEvent> notification, CancellationToken cancellationToken)
 {
     dispatchedMessages.Add(notification.IntegrationEvent);
     return(Task.CompletedTask);
 }