public IPusher CreatePusher(IIndexModel model)
 {
     if (model == null)
     {
         return(null);
     }
     using (var connectionRepository = ResolverFactory.Resolve <ConnectionRepository>())
         using (var entityRepository = ResolverFactory.Resolve <EntityRepository>())
         {
             var     destinationConnection = connectionRepository.GetById(model.DestinationConnectionId.ToString());
             IPusher result = null;
             if (model.EntityType == EntityType.Attribute)
             {
                 var attrModel   = model as AttributeModel;
                 var entityModel = entityRepository.GetById(attrModel.EntityId.ToString());
                 result = pushers
                          .Where(p => typeof(IAttributePusher).IsAssignableFrom(p.GetType()))
                          .Select(p => p as IAttributePusher)
                          .FirstOrDefault(p => p.IsImplemented(model.DestinationProcessorId, entityModel.DestinationProcessorId, destinationConnection.ProviderId));
             }
             else
             {
                 result = pushers
                          .Where(p => typeof(IEntityPusher).IsAssignableFrom(p.GetType()))
                          .Select(p => p as IEntityPusher)
                          .FirstOrDefault(p => p.IsImplemented(model.DestinationProcessorId, destinationConnection.ProviderId));
             }
             var options = entityRepository.LoadOptions(model.Id.ToString(), model.EntityType)
                           .Select(o => new OptionItem
             {
                 Name  = o.Key,
                 Value = o.Value
             });
             result.SetIndex(model);
             result.SetOptions(options);
             return(result);
         }
 }
Exemple #2
0
        public async Task <PushState> PushItem(IndexItemModel item)
        {
            Report($@"
---------------------------------------------------------------------------------
Begin synchronizing item {JsonConvert.SerializeObject(item, Formatting.Indented)}...");
            _pusher.SetIndex(_indexerModel);
            _pusher.SetItem(item);
            var result = await Task.Run(() =>
            {
                try
                {
                    entityRepository.BeginTransaction();
                    attributeRepository.BeginTransaction();
                    messageRepository.BeginTransaction();
                    var pushState     = PushState.Success;
                    var destinationId = item.GetDestinationId();
                    if (!string.IsNullOrWhiteSpace(destinationId))
                    {
                        if (item.HasState(ItemState.Removed))
                        {
                            _pusher.Remove();
                        }
                        else
                        {
                            _pusher.Update();
                        }
                    }
                    else
                    {
                        destinationId = _pusher.GetDestinationId();
                        if (!string.IsNullOrWhiteSpace(destinationId))
                        {
                            if (item.HasState(ItemState.Removed))
                            {
                                _pusher.Remove(destinationId);
                            }
                            else
                            {
                                _pusher.Update(destinationId);
                            }
                        }
                        else // still cannot find a destinationId, which means the entity/attribute does not exists
                        {
                            pushState = _pusher.Create(out destinationId);
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(destinationId) && (pushState & PushState.Success) > 0)
                    {
                        entityRepository.UpdateItemDestinationId(_indexerModel, item.GetSourceId(), destinationId);
                        // Detect dependencies that depends on "Synced" step
                        UpdateDependencies(item, destinationId);
                    }
                    else
                    {
                        // Signal to tell that the item is success or not
                        entityRepository.Retry(_indexerModel, item.GetId(), pushState);
                    }

                    entityRepository.Commit();
                    attributeRepository.Commit();
                    return(pushState);
                }
                catch
                {
                    entityRepository.RollBack();
                    attributeRepository.RollBack();
                    // Update invalid item
                    // Increate retry count
                    // Next time when queue items, it will be put behind because of the retry count
                    entityRepository.Retry(_indexerModel, item.GetId(), PushState.Failed);
                    throw;
                }
                finally
                {
                    Report($@"
Ended synchronizing...
---------------------------------------------------------------------------------
");
                }
            });

            return(result);
        }
        public override async Task Invoke(IStepExecutionContext context = null)
        {
            var executeAt       = DateTime.Now.ToUnixTimestamp();
            var firstQueuedItem = entityRepository.GetCurrentQueuedItems();

            if (firstQueuedItem == null)
            {
                return;
            }
            IIndexModel              indexModel = null;
            IndexItemModel           itemModel  = null;
            IIndexer                 indexer    = null;
            IPusher                  pusher     = null;
            IEnumerable <OptionItem> options    = null;

            if (firstQueuedItem.TargetEntityType == EntityType.Entity)
            {
                indexModel = entityRepository.GetById(firstQueuedItem.TargetEntityId.ToString());
                options    = entityRepository.LoadOptions(indexModel.Id.ToString()).Select(o => new OptionItem {
                    Name = o.Key, Value = o.Value
                });
                var sourceConnection      = connectionRepository.GetById(indexModel.SourceConnectionId.ToString());
                var destinationConnection = connectionRepository.GetById(indexModel.DestinationConnectionId.ToString());
                indexer = entityIndexers.FirstOrDefault(i => i.IsImplemented(indexModel.SourceProcessorId, sourceConnection.ProviderId));
                pusher  = entityPushers.FirstOrDefault(p => p.IsImplemented(indexModel.DestinationProcessorId, destinationConnection.ProviderId));
            }
            else
            {
                var attributeModel = attributeRepository.GetById(firstQueuedItem.TargetEntityId.ToString());
                indexModel = attributeModel;
                var entityModel = entityRepository.GetById(attributeModel.EntityId.ToString());
                options = attributeRepository.LoadOptions(attributeModel.Id.ToString()).Select(o => new OptionItem {
                    Name = o.Key, Value = o.Value
                });
                var sourceConnection      = connectionRepository.GetById(attributeModel.SourceConnectionId.ToString());
                var destinationConnection = connectionRepository.GetById(attributeModel.DestinationConnectionId.ToString());
                indexer = attributeIndexers.FirstOrDefault(i => i.IsImplemented(attributeModel.SourceProcessorId, entityModel.SourceProcessorId, sourceConnection.ProviderId));
                pusher  = attributePushers.FirstOrDefault(p => p.IsImplemented(attributeModel.DestinationProcessorId, entityModel.DestinationProcessorId, destinationConnection.ProviderId));
            }

            indexer.SetIndex(indexModel);
            indexer.SetOptions(options);
            pusher.SetIndex(indexModel);
            pusher.SetOptions(options);
            pusherManager.SetIndex(indexModel);
            pusherManager.OnReport(s => Logger.Information(s));
            pusherManager.SetIndexer(indexer);
            pusherManager.SetPusher(pusher);

            try
            {
                itemModel = entityRepository.GetIndexedItemById(indexModel, firstQueuedItem.TargetItemId.ToString());
                var pushState = await pusherManager.PushItem(itemModel);

                var queueItemStatus = firstQueuedItem.Status == PushState.None ? PushState.Success : firstQueuedItem.Status;
                var messageId       = messageRepository.Create(new
                {
                    Message     = string.Join("\n", pusherManager.GetReportMessages()),
                    CreatedAt   = DateTime.Now.ToUnixTimestamp(),
                    MessageType = MessageType.Information,
                    Status      = MessageStatus.None
                });
                queueItemStatus = queueItemStatus & pushState;
                if ((pushState & PushState.Success) <= 0)
                {
                    queueItemStatus = (queueItemStatus | PushState.Success) ^ (PushState.Success);
                }
                queueItemRepository.Update(firstQueuedItem.Id.ToString(), new
                {
                    UpdatedAt  = DateTime.Now.ToUnixTimestamp(),
                    ExecuteAt  = executeAt,
                    ExecutedAt = DateTime.Now.ToUnixTimestamp(),
                    MessageId  = messageId,
                    Status     = queueItemStatus
                });
            }
            catch (Exception ex)
            {
                var messages  = $@"Queue item (Id: {firstQueuedItem.Id}) failed to run. 
Addtional information:
```{JsonConvert.SerializeObject(indexModel, Formatting.Indented)}```
Progress: 
```{string.Join("\n - ", pusherManager.GetReportMessages())}```
Exception: 
```{ex}```";
                var messageId = messageRepository.Create(new
                {
                    Message     = messages,
                    CreatedAt   = DateTime.Now.ToUnixTimestamp(),
                    MessageType = MessageType.Error,
                    Status      = MessageStatus.None
                });

                queueItemRepository.Update(firstQueuedItem.Id.ToString(), new
                {
                    UpdatedAt  = DateTime.Now.ToUnixTimestamp(),
                    ExecuteAt  = executeAt,
                    ExecutedAt = DateTime.Now.ToUnixTimestamp(),
                    MessageId  = messageId,
                    Status     = (firstQueuedItem.Status | PushState.UnexpectedError | PushState.Failed | PushState.Success) ^ PushState.Success, // remove success
                });
                throw;
            }
        }