예제 #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());
        }
예제 #2
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 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());
        }
        public void Constructor_Always_UpdatesProperties()
        {
            var queryModelId      = Unified.NewCode();
            var queryModelVersion = FixtureUtils.Int();
            var queryModelType    = typeof(int);
            var operation         = FixtureUtils.FromEnum <QueryModelChangeOperation>();

            var signal = new QueryModelChangedSignal(queryModelId, queryModelVersion, queryModelType, operation);

            signal.QueryModelId.Should().Be(queryModelId);
            signal.QueryModelVersion.Should().Be(queryModelVersion);
            signal.QueryModelType.Should().Be(queryModelType);
            signal.Operation.Should().Be(operation);
        }
        public void QueryModelChangedSignal_Always_SerializedCorrectly()
        {
            var signal = new QueryModelChangedSignal(Unified.NewCode(), FixtureUtils.Int(), typeof(int), FixtureUtils.FromEnum <QueryModelChangeOperation>())
            {
                CorrelationId   = Unified.NewCode(),
                AggregateRootId = Unified.NewCode(),
                Metadata        = { [MetadataKey.UserId] = Unified.NewCode() },
                Actor           = { IdentityId = Unified.NewCode(), UserId = Unified.NewCode(), IsProcessManager = true }
            };

            var json         = JsonConvert.SerializeObject(signal);
            var deserialized = JsonConvert.DeserializeObject <QueryModelChangedSignal>(json);

            deserialized.Should().BeEquivalentTo(signal);
        }
예제 #7
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
            });
        }
예제 #8
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
            });
        }
예제 #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="QueryModelChangedNotification"/> class.
 /// </summary>
 /// <param name="signal">Value for <see cref="Signal"/>.</param>
 public QueryModelChangedNotification(QueryModelChangedSignal signal)
 {
     Signal = signal;
 }