public async Task ThenItShouldStoreNewVersionOfEntitiesThatAreNewlyLinked(SyncQueueItem queueItem, RegisteredEntity linkedEntity)
        {
            _matcherMock.Setup(m => m.MatchAsync(It.IsAny <Entity>(), It.IsAny <DateTime>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(
                new MatchResult
            {
                Synonyms = new MatchResultItem[0],
                Links    = new[]
                {
                    new MatchResultLink
                    {
                        RegisteredEntity = linkedEntity,
                        Entity           = linkedEntity.Entities[0],
                        LinkType         = "test",
                        MatchReason      = "Linked for testing",
                    },
                },
            });

            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.Is <RegisteredEntity[]>(entitiesToUpdate =>
                                                                  entitiesToUpdate.Count(update => update.Entities.Any(entity => ObjectAssert.AreEqual(queueItem.Entity, entity))) == 1 &&
                                                                  entitiesToUpdate.Count(update => AreEqual(linkedEntity.Entities, update.Entities) && update.Id != linkedEntity.Id) == 1 &&
                                                                  entitiesToUpdate.Count(update => update.Links.Count(link => link.LinkType == "test") == 1) == 2),
                                       It.IsAny <RegisteredEntity[]>(),
                                       _cancellationToken),
                                   Times.Once);
        }
        public async Task ThenItShouldDeleteLinkedEntityIfValidFromSameAsPointInTime(SyncQueueItem queueItem, RegisteredEntity linkedEntity)
        {
            linkedEntity.ValidFrom = queueItem.PointInTime;
            _matcherMock.Setup(m => m.MatchAsync(It.IsAny <Entity>(), It.IsAny <DateTime>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(
                new MatchResult
            {
                Synonyms = new MatchResultItem[0],
                Links    = new[]
                {
                    new MatchResultLink
                    {
                        RegisteredEntity = linkedEntity,
                        Entity           = linkedEntity.Entities[0],
                        LinkType         = "test",
                        MatchReason      = "Linked for testing",
                    },
                },
            });

            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.IsAny <RegisteredEntity[]>(),
                                       It.Is <RegisteredEntity[]>(entitiesToDelete =>
                                                                  entitiesToDelete.Count(update => update.Id == linkedEntity.Id) == 1),
                                       _cancellationToken),
                                   Times.Once);
        }
        public async Task ThenItShouldDeleteOldUnmatchedEntityIfSameAsPointInTime(SyncQueueItem queueItem)
        {
            _repositoryMock.Setup(r =>
                                  r.RetrieveAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <DateTime>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new RegisteredEntity
            {
                Id        = "old-entity",
                Type      = queueItem.Entity.Type,
                ValidFrom = queueItem.PointInTime,
                Entities  = new[]
                {
                    CloneLinkedEntity(queueItem.Entity, newName: "different name"),
                },
                Links = new Link[0],
            });

            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.Is <RegisteredEntity[]>(entitiesToUpdate =>
                                                                  entitiesToUpdate.Length == 1),
                                       It.Is <RegisteredEntity[]>(entitiesToDelete =>
                                                                  entitiesToDelete.Length == 1 &&
                                                                  entitiesToDelete.Any(x => x.Id == "old-entity")),
                                       _cancellationToken),
                                   Times.Once);
        }
        public async Task <string> EnqueueEntityForSyncAsync(SyncQueueItem queueItem, CancellationToken cancellationToken)
        {
            await _queue.CreateIfNotExistsAsync(cancellationToken);

            var message = new CloudQueueMessage(JsonConvert.SerializeObject(queueItem));
            await _queue.AddMessageAsync(message, cancellationToken);

            return(message.Id);
        }
        public async Task ThenItShouldDeserializeAndProcessTheQueueItem(SyncQueueItem syncQueueItem)
        {
            await _function.RunAsync(GetQueueMessage(syncQueueItem), _cancellationToken);

            _syncManagerMock.Verify(m => m.ProcessSyncQueueItemAsync(
                                        It.Is <SyncQueueItem>(actualQueueItem => ObjectAssert.AreEqual(syncQueueItem, actualQueueItem)),
                                        _cancellationToken),
                                    Times.Once);
        }
        public async Task ReceiveSyncEntityAsync <T>(SyncEntityEvent <T> @event, string sourceSystemName, CancellationToken cancellationToken)
            where T : EntityBase
        {
            var entity = MapEventToEntity(@event, sourceSystemName);

            var queueItem = new SyncQueueItem
            {
                Entity            = entity,
                PointInTime       = @event.PointInTime,
                InternalRequestId = _executionContextManager.SpiExecutionContext.InternalRequestId,
                ExternalRequestId = _executionContextManager.SpiExecutionContext.ExternalRequestId,
            };

            var messageId = await _syncQueue.EnqueueEntityForSyncAsync(queueItem, cancellationToken);

            _logger.Info($"Queued item with message id {messageId}");
        }
        public async Task ThenItShouldStoreNewMatchedEntity(SyncQueueItem queueItem, Entity synonymEntity)
        {
            synonymEntity.EntityType = queueItem.Entity.EntityType;
            _matcherMock.Setup(m => m.MatchAsync(It.IsAny <Entity>(), It.IsAny <DateTime>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new MatchResult
            {
                Synonyms = new[]
                {
                    new MatchResultItem
                    {
                        MatchReason      = "Matched for testing",
                        RegisteredEntity = new RegisteredEntity
                        {
                            Id        = "other-entity",
                            Type      = queueItem.Entity.EntityType,
                            ValidFrom = queueItem.PointInTime,
                            Entities  = new[]
                            {
                                CloneLinkedEntity(synonymEntity)
                            }
                        }
                    },
                },
                Links = new MatchResultLink[0],
            });

            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.Is <RegisteredEntity[]>(entitiesToUpdate =>
                                                                  entitiesToUpdate.Length == 1 &&
                                                                  entitiesToUpdate[0].Type == queueItem.Entity.EntityType &&
                                                                  entitiesToUpdate[0].ValidFrom == queueItem.PointInTime &&
                                                                  !entitiesToUpdate[0].ValidTo.HasValue &&
                                                                  entitiesToUpdate[0].Entities != null &&
                                                                  entitiesToUpdate[0].Entities.Length == 2 &&
                                                                  ObjectAssert.AreEqual(queueItem.Entity, entitiesToUpdate[0].Entities[0]) &&
                                                                  ObjectAssert.AreEqual(synonymEntity, entitiesToUpdate[0].Entities[1]) &&
                                                                  entitiesToUpdate[0].Links != null &&
                                                                  entitiesToUpdate[0].Links.Length == 0),
                                       It.IsAny <RegisteredEntity[]>(),
                                       _cancellationToken),
                                   Times.Once);
        }
        public async Task ThenItShouldNotUpdateLinkedEntityIfLinkAlreadyExists(SyncQueueItem queueItem, RegisteredEntity linkedEntity)
        {
            linkedEntity.ValidFrom = queueItem.PointInTime.AddDays(-1);
            linkedEntity.Links     = new[]
            {
                new Link
                {
                    EntityType       = queueItem.Entity.EntityType,
                    SourceSystemName = queueItem.Entity.SourceSystemName,
                    SourceSystemId   = queueItem.Entity.SourceSystemId,
                    LinkedAt         = queueItem.PointInTime.AddDays(-60),
                    LinkedBy         = "Unit test fixture",
                    LinkedReason     = "Testing existing links",
                    LinkType         = "test",
                },
            };
            _matcherMock.Setup(m => m.MatchAsync(It.IsAny <Entity>(), It.IsAny <DateTime>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(
                new MatchResult
            {
                Synonyms = new MatchResultItem[0],
                Links    = new[]
                {
                    new MatchResultLink
                    {
                        RegisteredEntity = linkedEntity,
                        Entity           = linkedEntity.Entities[0],
                        LinkType         = "test",
                        MatchReason      = "Linked for testing",
                    },
                },
            });

            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.Is <RegisteredEntity[]>(entitiesToUpdate =>
                                                                  entitiesToUpdate.Any(update => update.Id == linkedEntity.Id)),
                                       It.IsAny <RegisteredEntity[]>(),
                                       _cancellationToken),
                                   Times.Never);
        }
        public async Task ThenItShouldStoreNewUnmatchedEntity(SyncQueueItem queueItem)
        {
            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.Is <RegisteredEntity[]>(entitiesToUpdate =>
                                                                  entitiesToUpdate.Length == 1 &&
                                                                  entitiesToUpdate[0].Type == queueItem.Entity.EntityType &&
                                                                  entitiesToUpdate[0].ValidFrom == queueItem.PointInTime &&
                                                                  !entitiesToUpdate[0].ValidTo.HasValue &&
                                                                  entitiesToUpdate[0].Entities != null &&
                                                                  entitiesToUpdate[0].Entities.Length == 1 &&
                                                                  ObjectAssert.AreEqual(queueItem.Entity, entitiesToUpdate[0].Entities[0]) &&
                                                                  entitiesToUpdate[0].Links != null &&
                                                                  entitiesToUpdate[0].Links.Length == 0),
                                       It.Is <RegisteredEntity[]>(entitiesToDelete =>
                                                                  entitiesToDelete.Length == 0),
                                       _cancellationToken),
                                   Times.Once);
        }
        public async Task ProcessSyncQueueItemAsync(SyncQueueItem queueItem, CancellationToken cancellationToken)
        {
            _logger.Debug($"Trying to find existing entity for {queueItem.Entity} at {queueItem.PointInTime}");
            var existingEntity = await _repository.RetrieveAsync(
                queueItem.Entity.EntityType,
                queueItem.Entity.SourceSystemName,
                queueItem.Entity.SourceSystemId,
                queueItem.PointInTime,
                cancellationToken);

            var matchResult = await _matcher.MatchAsync(queueItem.Entity, queueItem.PointInTime, cancellationToken);

            _logger.Info($"Matching found {matchResult.Synonyms?.Length} synonyms and {matchResult.Links?.Length} links");

            var registeredEntity = GetRegisteredEntityForPointInTime(queueItem.Entity, queueItem.PointInTime, matchResult);

            await ProcessEntityChangesAsync(existingEntity, registeredEntity, matchResult, cancellationToken);

            _logger.Info($"Finished processing entity {queueItem.Entity} at {queueItem.PointInTime}");
        }
        public async Task ThenItShouldDeleteOldMatchedEntityIfSameAsPointInTime(SyncQueueItem queueItem, Entity synonymEntity)
        {
            synonymEntity.EntityType = queueItem.Entity.EntityType;
            _matcherMock.Setup(m => m.MatchAsync(It.IsAny <Entity>(), It.IsAny <DateTime>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new MatchResult
            {
                Synonyms = new[]
                {
                    new MatchResultItem
                    {
                        MatchReason      = "Matched for testing",
                        RegisteredEntity = new RegisteredEntity
                        {
                            Id        = "other-entity",
                            Type      = queueItem.Entity.EntityType,
                            ValidFrom = queueItem.PointInTime,
                            Entities  = new[]
                            {
                                CloneLinkedEntity(synonymEntity)
                            }
                        }
                    },
                },
                Links = new MatchResultLink[0],
            });

            await _syncManager.ProcessSyncQueueItemAsync(queueItem, _cancellationToken);

            _repositoryMock.Verify(r => r.StoreAsync(
                                       It.Is <RegisteredEntity[]>(entitiesToUpdate =>
                                                                  entitiesToUpdate.Length == 1),
                                       It.Is <RegisteredEntity[]>(entitiesToDelete =>
                                                                  entitiesToDelete.Length == 1 &&
                                                                  entitiesToDelete.Any(x => x.Id == "other-entity")),
                                       _cancellationToken),
                                   Times.Once);
        }
 private CloudQueueMessage GetQueueMessage(SyncQueueItem content)
 {
     return(new CloudQueueMessage(JsonConvert.SerializeObject(content)));
 }
Beispiel #13
0
 public Task <string> EnqueueEntityForSyncAsync(SyncQueueItem queueItem, CancellationToken cancellationToken)
 {
     _queue.Enqueue(queueItem);
     return(Task.FromResult(Guid.NewGuid().ToString()));
 }