private IEntitySyncState <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity> CreateInitialSyncState( IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> knownEntityRelation, bool newAVersionAvailable, TAtypeEntityVersion newAVersion, bool newBVersionAvailable, TBtypeEntityVersion newBVersion, VersionDeltaLoginInformation aLogInfo, VersionDeltaLoginInformation bLogInfo) { IEntitySyncState <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity> state; if (newAVersionAvailable) { var aChanged = !_atypeVersionComparer.Equals(newAVersion, knownEntityRelation.AtypeVersion); if (aChanged) { aLogInfo.IncChanged(); if (newBVersionAvailable) { var bChanged = !_btypeVersionComparer.Equals(newBVersion, knownEntityRelation.BtypeVersion); if (bChanged) { bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Changed(knownEntityRelation, newAVersion, newBVersion); } else { bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Unchanged(knownEntityRelation, newAVersion); } } else { bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Deleted(knownEntityRelation, newAVersion); } } else { aLogInfo.IncUnchanged(); if (newBVersionAvailable) { var bChanged = !_btypeVersionComparer.Equals(newBVersion, knownEntityRelation.BtypeVersion); if (bChanged) { bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Changed(knownEntityRelation, newBVersion); } else { bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Unchanged(knownEntityRelation); } } else { bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Deleted(knownEntityRelation); } } } else { aLogInfo.IncDeleted(); if (newBVersionAvailable) { var bChanged = !_btypeVersionComparer.Equals(newBVersion, knownEntityRelation.BtypeVersion); if (bChanged) { bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Changed(knownEntityRelation, newBVersion); } else { bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Unchanged(knownEntityRelation); } } else { bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Deleted(knownEntityRelation); } } return(state); }
private async Task <List <IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> > > Synchronize( ITotalProgressLogger totalProgress, IEnumerable <IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> > knownEntityRelations, Dictionary <TAtypeEntityId, TAtypeEntityVersion> newAVersions, Dictionary <TBtypeEntityId, TBtypeEntityVersion> newBVersions, EntityContainer entityContainer, ISynchronizationLogger logger, TContext synchronizationContext, ISynchronizationInterceptor <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext> interceptor) { var entitySyncStates = new EntitySyncStateContainer <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext>(); var aDeltaLogInfo = new VersionDeltaLoginInformation(); var bDeltaLogInfo = new VersionDeltaLoginInformation(); foreach (var knownEntityRelationData in knownEntityRelations) { TAtypeEntityVersion newAVersion; TBtypeEntityVersion newBVersion; var newAVersionAvailable = newAVersions.TryGetValue(knownEntityRelationData.AtypeId, out newAVersion); var newBVersionAvailable = newBVersions.TryGetValue(knownEntityRelationData.BtypeId, out newBVersion); if (newAVersionAvailable) { newAVersions.Remove(knownEntityRelationData.AtypeId); } if (newBVersionAvailable) { newBVersions.Remove(knownEntityRelationData.BtypeId); } var entitySyncState = CreateInitialSyncState(knownEntityRelationData, newAVersionAvailable, newAVersion, newBVersionAvailable, newBVersion, aDeltaLogInfo, bDeltaLogInfo); entitySyncStates.Add(entitySyncState); } HashSet <TAtypeEntityId> aEntitesToLoad = new HashSet <TAtypeEntityId>(); HashSet <TBtypeEntityId> bEntitesToLoad = new HashSet <TBtypeEntityId>(); entitySyncStates.Execute(s => s.AddRequiredEntitiesToLoad(aEntitesToLoad.Add, bEntitesToLoad.Add)); await _atypeRepository.VerifyUnknownEntities(newAVersions, synchronizationContext); await _btypeRepository.VerifyUnknownEntities(newBVersions, synchronizationContext); if (newAVersions.Count > 0 && newBVersions.Count > 0) { foreach (var newA in newAVersions) { aEntitesToLoad.Add(newA.Key); } foreach (var newB in newBVersions) { bEntitesToLoad.Add(newB.Key); } await entityContainer.EnsureEntitiesLoaded(aEntitesToLoad, bEntitesToLoad, synchronizationContext); var newAtypeEntities = GetSubSet(entityContainer.AEntities, newAVersions.Keys, _atypeIdComparer); var newBtypeEntities = GetSubSet(entityContainer.BEntities, newBVersions.Keys, _btypeIdComparer); var matchingEntites = _initialEntityMatcher.FindMatchingEntities( _entityRelationDataFactory, newAtypeEntities, newBtypeEntities, newAVersions, newBVersions); foreach (var knownEntityRelationData in matchingEntites) { newAVersions.Remove(knownEntityRelationData.AtypeId); newBVersions.Remove(knownEntityRelationData.BtypeId); var entitySyncState = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Unchanged(knownEntityRelationData); entitySyncStates.Add(entitySyncState); aDeltaLogInfo.IncUnchanged(); bDeltaLogInfo.IncUnchanged(); } } foreach (var newA in newAVersions) { var syncState = _initialSyncStateCreationStrategy.CreateFor_Added_NotExisting(newA.Key, newA.Value); entitySyncStates.Add(syncState); } foreach (var newB in newBVersions) { var syncState = _initialSyncStateCreationStrategy.CreateFor_NotExisting_Added(newB.Key, newB.Value); entitySyncStates.Add(syncState); } entitySyncStates.TransformStates(s => interceptor.TransformInitialCreatedStates(s, _syncStateFactory)); entitySyncStates.Execute(s => s.AddRequiredEntitiesToLoad(aEntitesToLoad.Add, bEntitesToLoad.Add)); await entityContainer.EnsureEntitiesLoaded(aEntitesToLoad, bEntitesToLoad, synchronizationContext); // all the leftovers in newAVersions and newBVersions must be the added ones aDeltaLogInfo.IncAdded(newAVersions.Count); bDeltaLogInfo.IncAdded(newBVersions.Count); s_logger.InfoFormat("Atype delta: {0}", aDeltaLogInfo); s_logger.InfoFormat("Btype delta: {0}", bDeltaLogInfo); logger.LogDeltas(aDeltaLogInfo, bDeltaLogInfo); entitySyncStates.DoTransition(s => s.FetchRequiredEntities(entityContainer.AEntities, entityContainer.BEntities)); entitySyncStates.DoTransition(s => s.Resolve()); // since resolve may change to an new state, required entities have to be fetched again. // an state is allowed only to resolve to another state, if the following states requires equal or less entities! entitySyncStates.DoTransition(s => s.FetchRequiredEntities(entityContainer.AEntities, entityContainer.BEntities)); var aJobs = new JobList <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity> (); var bJobs = new JobList <TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity> (); entitySyncStates.Execute(s => s.AddSyncronizationJob(aJobs, bJobs, logger.CreateEntitySynchronizationLogger(), synchronizationContext)); s_logger.InfoFormat($"A repository jobs: Create {aJobs.CreateJobs.Count} , Update {aJobs.UpdateJobs.Count} , Delete {aJobs.DeleteJobs.Count}"); s_logger.InfoFormat($"B repository jobs: Create {bJobs.CreateJobs.Count} , Update {bJobs.UpdateJobs.Count} , Delete {bJobs.DeleteJobs.Count}"); using (var progress = totalProgress.StartProcessing(aJobs.TotalJobCount + bJobs.TotalJobCount)) { await _atypeWriteRepository.PerformOperations(aJobs.CreateJobs, aJobs.UpdateJobs, aJobs.DeleteJobs, progress, synchronizationContext); await _btypeWriteRepository.PerformOperations(bJobs.CreateJobs, bJobs.UpdateJobs, bJobs.DeleteJobs, progress, synchronizationContext); } entitySyncStates.DoTransition(s => s.NotifyJobExecuted()); var newEntityRelations = new List <IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> >(); entitySyncStates.Execute(s => s.AddNewRelationNoThrow(newEntityRelations.Add)); entitySyncStates.Dispose(); return(newEntityRelations); }
private async Task <IReadOnlyList <IEntitySyncStateContext <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext> > > CreateEntitySyncStateContexts( IEntityContainer <TAtypeEntityId, TAtypeEntity, TContext> aEntities, IEntityContainer <TBtypeEntityId, TBtypeEntity, TContext> bEntities, IEnumerable <IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> > knownEntityRelations, IEntityStateCollection <TAtypeEntityId, TAtypeEntityVersion> aStates, IEntityStateCollection <TBtypeEntityId, TBtypeEntityVersion> bStates, ISynchronizationLogger logger, TContext synchronizationContext, ISynchronizationInterceptor <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext> interceptor) { var entitySynchronizationContexts = new List <IEntitySyncStateContext <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext> >(); var aDeltaLogInfo = new VersionDeltaLoginInformation(); var bDeltaLogInfo = new VersionDeltaLoginInformation(); foreach (var knownEntityRelationData in knownEntityRelations) { (var aState, var aRepositoryVersion) = aStates.RemoveState(knownEntityRelationData.AtypeId, knownEntityRelationData.AtypeVersion); (var bState, var bRepositoryVersion) = bStates.RemoveState(knownEntityRelationData.BtypeId, knownEntityRelationData.BtypeVersion); entitySynchronizationContexts.Add(new EntitySyncStateContext <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext>( CreateInitialSyncState(knownEntityRelationData, aState, bState, aRepositoryVersion, bRepositoryVersion, aDeltaLogInfo, bDeltaLogInfo))); } var newAVersions = aStates.DisposeAndGetLeftovers(); var newBVersions = bStates.DisposeAndGetLeftovers(); await _atypeRepository.VerifyUnknownEntities(newAVersions, synchronizationContext); await _btypeRepository.VerifyUnknownEntities(newBVersions, synchronizationContext); if (newAVersions.Count > 0 && newBVersions.Count > 0) { s_logger.Info($"Performing entity matching with {newAVersions.Count} Atype and {newBVersions.Count} Btype entities."); var matchingEntites = _initialEntityMatcher.FindMatchingEntities( _entityRelationDataFactory, await aEntities.GetTransformedEntities(newAVersions.Keys, logger.ALoadEntityLogger, synchronizationContext, e => _aMatchDataFactory.CreateMatchData(e.Entity)), await bEntities.GetTransformedEntities(newBVersions.Keys, logger.BLoadEntityLogger, synchronizationContext, e => _bMatchDataFactory.CreateMatchData(e.Entity)), newAVersions, newBVersions); foreach (var knownEntityRelationData in matchingEntites) { newAVersions.Remove(knownEntityRelationData.AtypeId); newBVersions.Remove(knownEntityRelationData.BtypeId); var entitySyncState = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Unchanged(knownEntityRelationData); entitySynchronizationContexts.Add(new EntitySyncStateContext <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext>(entitySyncState)); aDeltaLogInfo.IncUnchanged(); bDeltaLogInfo.IncUnchanged(); } s_logger.Info("Entity matching finished."); } foreach (var newA in newAVersions) { var syncState = _initialSyncStateCreationStrategy.CreateFor_Added_NotExisting(newA.Key, newA.Value); entitySynchronizationContexts.Add(new EntitySyncStateContext <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext>(syncState)); } foreach (var newB in newBVersions) { var syncState = _initialSyncStateCreationStrategy.CreateFor_NotExisting_Added(newB.Key, newB.Value); entitySynchronizationContexts.Add(new EntitySyncStateContext <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext>(syncState)); } interceptor.TransformInitialCreatedStates(entitySynchronizationContexts, _syncStateFactory); // all the leftovers in newAVersions and newBVersions must be the added ones aDeltaLogInfo.IncAdded(newAVersions.Count); bDeltaLogInfo.IncAdded(newBVersions.Count); s_logger.InfoFormat("Atype delta: {0}", aDeltaLogInfo); s_logger.InfoFormat("Btype delta: {0}", bDeltaLogInfo); logger.LogDeltas(aDeltaLogInfo, bDeltaLogInfo); return(entitySynchronizationContexts); }
private IEntitySyncState <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext> CreateInitialSyncState( IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> knownEntityRelation, EntityState aState, EntityState bState, TAtypeEntityVersion aRepositoryVersion, TBtypeEntityVersion bRepositoryVersion, VersionDeltaLoginInformation aLogInfo, VersionDeltaLoginInformation bLogInfo) { IEntitySyncState <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity, TContext> state; switch (aState) { case EntityState.ChangedOrAdded: aLogInfo.IncChanged(); switch (bState) { case EntityState.ChangedOrAdded: bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Changed(knownEntityRelation, aRepositoryVersion, bRepositoryVersion); break; case EntityState.Unchanged: bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Unchanged(knownEntityRelation, aRepositoryVersion); break; case EntityState.Deleted: bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Deleted(knownEntityRelation, aRepositoryVersion); break; default: throw new NotImplementedException($"'{bState}' not implemented"); } break; case EntityState.Unchanged: aLogInfo.IncUnchanged(); switch (bState) { case EntityState.ChangedOrAdded: bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Changed(knownEntityRelation, bRepositoryVersion); break; case EntityState.Unchanged: bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Unchanged(knownEntityRelation); break; case EntityState.Deleted: bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Deleted(knownEntityRelation); break; default: throw new NotImplementedException($"'{bState}' not implemented"); } break; case EntityState.Deleted: aLogInfo.IncDeleted(); switch (bState) { case EntityState.ChangedOrAdded: bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Changed(knownEntityRelation, bRepositoryVersion); break; case EntityState.Unchanged: bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Unchanged(knownEntityRelation); break; case EntityState.Deleted: bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Deleted(knownEntityRelation); break; default: throw new NotImplementedException($"'{bState}' not implemented"); } break; default: throw new NotImplementedException($"'{aState}' not implemented"); } return(state); }
private IEntitySyncState <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity> CreateInitialSyncState( IEntityRelationData <TAtypeEntityId, TAtypeEntityVersion, TBtypeEntityId, TBtypeEntityVersion> cachedData, bool repositoryAVersionAvailable, TAtypeEntityVersion repositoryAVersion, bool repositoryBVersionAvailable, TBtypeEntityVersion repositoryBVersion, VersionDeltaLoginInformation aLogInfo, VersionDeltaLoginInformation bLogInfo) { IEntitySyncState <TAtypeEntityId, TAtypeEntityVersion, TAtypeEntity, TBtypeEntityId, TBtypeEntityVersion, TBtypeEntity> state; if (repositoryAVersionAvailable) { var aChanged = !_atypeVersionComparer.Equals(repositoryAVersion, cachedData.AtypeVersion); if (aChanged) { aLogInfo.IncChanged(); if (repositoryBVersionAvailable) { var bChanged = !_btypeVersionComparer.Equals(repositoryBVersion, cachedData.BtypeVersion); if (bChanged) { bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Changed(cachedData, repositoryAVersion, repositoryBVersion); } else { bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Unchanged(cachedData, repositoryAVersion); } } else { bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Changed_Deleted(cachedData, repositoryAVersion); } } else { aLogInfo.IncUnchanged(); if (repositoryBVersionAvailable) { var bChanged = !_btypeVersionComparer.Equals(repositoryBVersion, cachedData.BtypeVersion); if (bChanged) { bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Changed(cachedData, repositoryBVersion); } else { bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Unchanged(cachedData); } } else { bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Unchanged_Deleted(cachedData); } } } else { aLogInfo.IncDeleted(); if (repositoryBVersionAvailable) { var bChanged = !_btypeVersionComparer.Equals(repositoryBVersion, cachedData.BtypeVersion); if (bChanged) { bLogInfo.IncChanged(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Changed(cachedData, repositoryBVersion); } else { bLogInfo.IncUnchanged(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Unchanged(cachedData); } } else { bLogInfo.IncDeleted(); state = _initialSyncStateCreationStrategy.CreateFor_Deleted_Deleted(cachedData); } } return(state); }