public async Task QueueChanges() { await Task.Run(() => { var limit = 100; var offset = 0; var dependencies = entityRepository.GetDependencies(_indexerModel.Id, _indexerModel.EntityType); var dependsOnEntities = entityRepository.GetByIds(dependencies.Where(d => d.TargetEntityType == EntityType.Entity).Select(d => d.TargetEntityId.ToString())) .Select(e => e as IIndexModel); var dependsOnAttributes = attributeRepository.GetByIds(dependencies.Where(d => d.TargetEntityType == EntityType.Attribute).Select(d => d.TargetEntityId.ToString())) .Select(e => e as IIndexModel); var dependsOnIndexes = dependsOnEntities.Union(dependsOnAttributes); while (true) { var changedItems = entityRepository.GetIndexChangedItems(_indexerModel, limit, offset, out int totalcount); if (changedItems.Count() <= 0) { break; } // Items that has been changed OR not synced yet and should be valid foreach (var item in changedItems) { var relatedItemNotSynced = false; var relatedItemNotFound = false; if (_indexerModel.EntityType == EntityType.Attribute) { var attributeModel = (AttributeModel)_indexerModel; var entityModel = entityRepository.GetById(attributeModel.EntityId.ToString()); var entityIndexItem = entityRepository.GetIndexedItemBySourceId(entityModel, item.GetSourceId()); if (entityIndexItem == null || !entityIndexItem.HasValues) { relatedItemNotFound = true; } else if (string.IsNullOrWhiteSpace(entityIndexItem.GetDestinationId())) { relatedItemNotSynced = true; } if (relatedItemNotSynced) { /** * Adding these status only for reporting */ entityRepository.AddIndexItemState( _indexerModel.ValueTableName, item.GetId(), relatedItemNotFound ? ItemState.RelatedItemNotFound : ItemState.RelatedItemNotSynced); continue; } } // Items that has dependencies that are not resolved/synced should not be queued var shouldNotSync = false; foreach (var dependence in dependencies) { var model = dependsOnIndexes.FirstOrDefault(d => d.Id == dependence.TargetEntityId && d.EntityType == dependence.TargetEntityType); var dependsOnItem = entityRepository.GetDependsOnItem(model.ValueTableName, dependence, item); if (dependsOnItem == null || !dependsOnItem.HasValues) { // should let item wait for it relatedItemNotFound = true; } else if (string.IsNullOrWhiteSpace(dependsOnItem["DestinationId"]?.ToString())) { // should let item wait for it relatedItemNotSynced = true; } else if (dependsOnItem.HasState(ItemState.Failed | ItemState.ValidationFailed | ItemState.Invalid | ItemState.RelatedItemNotFound | ItemState.RelatedItemNotSynced)) { shouldNotSync = true; } if (relatedItemNotSynced || relatedItemNotFound || shouldNotSync) { break; } } if (relatedItemNotSynced) { /** * Adding these status only for reporting */ entityRepository.AddIndexItemState( _indexerModel.ValueTableName, item.GetId(), relatedItemNotFound ? ItemState.RelatedItemNotFound : ItemState.RelatedItemNotSynced); continue; } if (shouldNotSync) { continue; } // TODO: what if retrycount > 1000? // TODO: what about Failed and ValidationFailed entityRepository.RemoveIndexItemState( _indexerModel.ValueTableName, item.GetId(), ItemState.RelatedItemNotFound | ItemState.RelatedItemNotSynced); // only valid item can be queued entityRepository.QueueItem(_indexerModel, item.GetId()); } offset += limit; } }); }