Example #1
0
            private int?GetUserId(string slug, string version, string token, string method)
            {
                var customer    = _connectionProvider.GetCustomer();
                var dbConnector = new DBConnector(customer.ConnectionString, customer.DatabaseType);

                var dbCommand = dbConnector.CreateDbCommand();

                if (slug == null || version == null)
                {
                    dbCommand.CommandText = GetCommonQuery(method, customer.DatabaseType);
                }
                else
                {
                    dbCommand.CommandText = GetServiceQuery(method, customer.DatabaseType);
                    dbCommand.Parameters.AddWithValue("@slug", slug.ToLower());
                    dbCommand.Parameters.AddWithValue("@version", version.ToLower());
                }

                var tokenParameter = dbCommand.Parameters.AddWithValue("@token", (object)token ?? DBNull.Value);

                tokenParameter.DbType = DbType.String;

                var dt      = dbConnector.GetRealData(dbCommand);
                var userIds = dt.AsEnumerable()
                              .Select(row => row["UserId"] == DBNull.Value ? null : (int?)(decimal?)row["UserId"]).ToArray();

                if (userIds.Any())
                {
                    return(userIds.First() ?? GetDefaultUserId());
                }
                return(null);
            }
 public QpMonitoringRepository(IConnectionProvider connectionProvider, IArticleFormatter formatter, bool state, string language)
 {
     _customer = connectionProvider.GetCustomer();
     _state    = state;
     _language = String.IsNullOrEmpty(language) ? "invariant" : language;
     _isJson   = formatter is JsonProductFormatter;
 }
Example #3
0
 public EditorLocaleService(
     IUserProvider userProvider,
     IConnectionProvider connectionProvider)
 {
     _userProvider = userProvider;
     _customer     = connectionProvider.GetCustomer();
 }
Example #4
0
 public ValidationService(ISettingsService settingsService, IUserProvider userProvider, IConnectionProvider connectionProvider, IArticleService articleService, ILogger logger)
 {
     _settingsService = settingsService;
     _userProvider    = userProvider;
     _articleService  = articleService;
     _logger          = logger;
     _customer        = connectionProvider.GetCustomer();
 }
 public ContentDefinitionService(ISettingsService settingsService,
                                 VersionedCacheProviderBase cacheProvider,
                                 IArticleService articleService,
                                 IConnectionProvider connectionProvider)
 {
     _settingsService = settingsService;
     _cacheProvider   = cacheProvider;
     _articleService  = articleService;
     _customer        = connectionProvider.GetCustomer();
 }
Example #6
0
        public ContentServiceAdapter(ContentService contentService, IConnectionProvider connectionProvider)
        {
            if (contentService == null)
            {
                throw new ArgumentNullException(nameof(contentService));
            }

            _contentService = contentService;

            _customer = connectionProvider.GetCustomer();
        }
Example #7
0
        public FieldServiceAdapter(FieldService fieldService, IConnectionProvider connectionProvider)
        {
            if (fieldService == null)
            {
                throw new ArgumentNullException(nameof(fieldService));
            }

            _fieldService = fieldService;
            _fieldMap     = new ConcurrentDictionary <int, Field>();

            _customer = connectionProvider.GetCustomer();
        }
Example #8
0
 public FreezeService(ISettingsService settingsService, IUserProvider userProvider, IConnectionProvider connectionProvider, ILogger logger)
 {
     _settingsService     = settingsService;
     _userProvider        = userProvider;
     _customer            = connectionProvider.GetCustomer();
     _freezeFieldName     = _settingsService.GetSetting(SettingsTitles.PRODUCT_FREEZE_FIELD_NAME);
     _typeFieldName       = _settingsService.GetSetting(SettingsTitles.PRODUCT_TYPES_FIELD_NAME);
     _productContentId    = int.Parse(_settingsService.GetSetting(SettingsTitles.PRODUCTS_CONTENT_ID));
     _definitionContentId =
         int.Parse(_settingsService.GetSetting(SettingsTitles.PRODUCT_DEFINITIONS_CONTENT_ID));
     _logger = logger;
 }
Example #9
0
        public ProductDeserializer(IFieldService fieldService, IServiceFactory serviceFactory, ICacheItemWatcher cacheItemWatcher, IContextStorage contextStorage, IConnectionProvider connectionProvider)
        {
            _fieldService = fieldService;

            _contentService = serviceFactory.GetContentService();

            _cacheItemWatcher = cacheItemWatcher;

            _contextStorage = contextStorage;

            _customer = connectionProvider.GetCustomer();
        }
        public ReadOnlyArticleServiceAdapter(ArticleService articleService, IConnectionProvider connectionProvider, IContextStorage contextStorage)
        {
            if (articleService == null)
            {
                throw new ArgumentNullException("articleService");
            }

            ArticleService = articleService;

            QpCustomer = connectionProvider.GetCustomer();

            ContextStorage = contextStorage;
        }
Example #11
0
        public ArticleDependencyService(IContentDefinitionService contentDefinitionService, IServiceFactory serviceFactory, VersionedCacheProviderBase cacheProvider, ISettingsService settingsService, IConnectionProvider connectionProvider)
        {
            _contentDefinitionService = contentDefinitionService;

            _customer = connectionProvider.GetCustomer();

            _cacheProvider = cacheProvider;

            _prodDefContentId = int.Parse(settingsService.GetSetting(SettingsTitles.PRODUCT_DEFINITIONS_CONTENT_ID));

            _articleService = serviceFactory.GetArticleService();

            _fieldService = serviceFactory.GetFieldService();
        }
Example #12
0
        public CustomerCodeInstance(IConnectionProvider connectionProvider, ILogger logger)
        {
            CacheProvider = new VersionedCacheProviderBase(logger);
            Invalidator   = new DpcContentInvalidator(CacheProvider, logger);

            var customer = connectionProvider.GetCustomer();

            if (customer != null)
            {
                Watcher = new CustomerCoreCacheItemWatcher(InvalidationMode.All, TimeSpan.FromSeconds(15),
                                                           Invalidator, connectionProvider, logger, databaseType: customer.DatabaseType);
                Tracker = new StructureCacheTracker(customer.ConnectionString, customer.DatabaseType);
                Watcher.AttachTracker(Tracker);
                ((CacheItemWatcherBase)Watcher).Start();
            }
        }
Example #13
0
 public XmlProductService(
     ILogger logger,
     ISettingsService settingsService,
     IConnectionProvider connectionProvider,
     IRegionTagReplaceService regionTagReplaceService,
     IOptions <LoaderProperties> loaderProperties,
     IHttpClientFactory factory
     )
 {
     _logger                  = logger;
     _settingsService         = settingsService;
     _regionTagReplaceService = regionTagReplaceService;
     _customer                = connectionProvider.GetCustomer();
     _loaderProperties        = loaderProperties.Value;
     _factory                 = factory;
 }
Example #14
0
        public EditorSchemaService(
            IConnectionProvider connectionProvider,
            IReadOnlyArticleService articleService,
            ContentService contentService,
            FieldService fieldService,
            VirtualFieldContextService virtualFieldContextService,
            EditorPreloadingService editorPreloadingService)
        {
            var customer = connectionProvider.GetCustomer();

            _dbConnector                = new DBConnector(customer.ConnectionString, customer.DatabaseType);
            _articleService             = articleService;
            _contentService             = contentService;
            _fieldService               = fieldService;
            _virtualFieldContextService = virtualFieldContextService;
            _editorPreloadingService    = editorPreloadingService;
        }
Example #15
0
        public Transaction(IConnectionProvider connectionProvider, ILogger logger)
        {
            _transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                     new TransactionOptions {
                Timeout = connectionProvider.TransactionTimeout, IsolationLevel = IsolationLevel.ReadCommitted
            });
            var current = QPConnectionScope.Current;

            if (current != null && current.DbConnection != null)
            {
                logger.Error("There was a try to create transaction for existing connection. Status: " + current.DbConnection.State);
            }

            var customer = connectionProvider.GetCustomer();

            _connectionScope = new QPConnectionScope(customer.ConnectionString, (DatabaseType)customer.DatabaseType);
        }
Example #16
0
        public RegionTagService(VersionedCacheProviderBase cacheProvider, ISettingsService settingsService,
                                IRegionService regionService, IArticleService articleService, IFieldService fieldService,
                                IConnectionProvider connectionProvider)
        {
            _cacheProvider   = cacheProvider;
            _settingsService = settingsService;
            _regionService   = regionService;
            _articleService  = articleService;
            _fieldService    = fieldService;
            _customer        = connectionProvider.GetCustomer();

            TagsContentId      = int.Parse(_settingsService.GetSetting(SettingsTitles.REGIONAL_TAGS_CONTENT_ID));
            TagValuesContentId = int.Parse(_settingsService.GetSetting(SettingsTitles.REGIONAL_TAGS_VALUES_CONTENT_ID));
            RegionsContentId   = int.Parse(_settingsService.GetSetting(SettingsTitles.REGIONS_CONTENT_ID));
            TagTitleName       = _settingsService.GetSetting(SettingsTitles.REGIONAL_TAGS_KEY_FIELD_NAME) ?? "Title";
            TagValueName       = _settingsService.GetSetting(SettingsTitles.REGIONAL_TAGS_VALUES_VALUE_FIELD_NAME) ?? "Value";
        }
Example #17
0
        public ServiceFactory(IConnectionProvider connectionProvider, IUserProvider userProvider)
        {
            //TODO: Use code contracts instead of code below

            if (connectionProvider == null)
            {
                throw new ArgumentNullException("connectionProvider");
            }

            if (userProvider == null)
            {
                throw new ArgumentNullException("userProvider");
            }


            _customer     = connectionProvider.GetCustomer();
            _userProvider = userProvider;
        }
Example #18
0
        public static NotificationsModelDataContext Get(IConnectionProvider provider)
        {
            var customerConfig = provider.GetCustomer(QP.Models.Service.Notification);
            NotificationsModelDataContext result;

            if (customerConfig.DatabaseType == DatabaseType.Postgres)
            {
                var optionsBuilder = new DbContextOptionsBuilder <NpgSqlNotificationsModelDataContext>();
                optionsBuilder.UseNpgsql(customerConfig.ConnectionString);
                result = new NpgSqlNotificationsModelDataContext(optionsBuilder.Options);
            }
            else
            {
                var optionsBuilder = new DbContextOptionsBuilder <SqlServerNotificationsModelDataContext>();
                optionsBuilder.UseSqlServer(customerConfig.ConnectionString);
                result = new SqlServerNotificationsModelDataContext(optionsBuilder.Options);
            }

            return(result);
        }
Example #19
0
        public JsonProductService(
            IConnectionProvider connectionProvider,
            ILogger logger,
            ContentService contentService,
            FieldService fieldService,
            VirtualFieldContextService virtualFieldContextService,
            IRegionTagReplaceService regionTagReplaceService,
            IOptions<LoaderProperties> loaderProperties,
            IHttpClientFactory factory            
            )
        {
            _logger = logger;
            _contentService = contentService;
            _fieldService = fieldService;

            var customer = connectionProvider.GetCustomer();
            _dbConnector = new DBConnector(customer.ConnectionString, customer.DatabaseType);

            _virtualFieldContextService = virtualFieldContextService;
            _regionTagReplaceService = regionTagReplaceService;
            _loaderProperties = loaderProperties.Value;
            _factory = factory;
        }
        public override ActionTaskResult Process(ActionContext context)
        {
            int marketingProductContentId = int.Parse(_settingsService.GetSetting(SettingsTitles.MARKETING_PRODUCT_CONTENT_ID));

            int[] productIds = context.ContentId == marketingProductContentId
                ? Helpers.GetProductIdsFromMarketingProducts(context.ContentItemIds, _articleService, _settingsService)
                : context.ContentItemIds;

            if (productIds == null || productIds.Length == 0)
            {
                if (context.ContentId == marketingProductContentId)
                {
                    throw new Exception("Unable to process all marketing products. Please, select specific ones");
                }

                productIds = Helpers.GetAllProductIds(int.Parse(context.Parameters["site_id"]), context.ContentId, _provider.GetCustomer());
            }

            object percentLocker = new object();

            float percentPerProduct = (float)100 / productIds.Length;

            float currentPercent = 0;

            const byte tasksCount = 15;

            const int minBundleSize = 15;

            int bundleSize = Math.Max(productIds.Length / tasksCount, minBundleSize);

            var sectionedProductIds = productIds.Section(bundleSize).ToArray();

            var tasks = sectionedProductIds
                        .Select(x => Task.Factory.StartNew(
                                    productIdsInSection =>
            {
                var productRelevanceService = ObjectFactoryBase.Resolve <IProductRelevanceService>();
                var productService          = ObjectFactoryBase.Resolve <IProductService>();

                foreach (int productId in (IList <int>)productIdsInSection)
                {
                    foreach (var isLive in new[] { true, false })
                    {
                        var product        = productService.GetProductById(productId, isLive);
                        var relevanceItems = productRelevanceService.GetProductRelevance(product, isLive, true);

                        foreach (var relevanceItem in relevanceItems)
                        {
                            var consumerMonitoringService = _consumerMonitoringServiceFunc(true, relevanceItem.Culture);

                            if (consumerMonitoringService != null)
                            {
                                consumerMonitoringService.InsertOrUpdateProductRelevanceStatus(productId, relevanceItem.Relevance, isLive);
                            }

                            if (TaskContext.IsCancellationRequested)
                            {
                                TaskContext.IsCancelled = true;
                                return;
                            }
                        }
                    }

                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;
                        return;
                    }

                    lock (percentLocker)
                    {
                        currentPercent += percentPerProduct;
                    }

                    TaskContext.SetProgress((byte)currentPercent);
                }
            },
                                    x,
                                    TaskCreationOptions.LongRunning))
                        .ToArray();

            Task.WaitAll(tasks);

            return(ActionTaskResult.Success(new ActionTaskResultMessage()
            {
                ResourceClass = nameof(TaskStrings),
                ResourceName = nameof(TaskStrings.StatusesUpdated),
                Parameters = new object[] { productIds.Length }
            }));
        }
Example #21
0
        public static TaskRunnerEntities Get(IConnectionProvider provider)
        {
            var customerConfig = provider.GetCustomer(Service.Actions);

            return(Get(customerConfig));
        }
 public PublicationStatusService(IConnectionProvider connectionProvider)
 {
     _customer = connectionProvider.GetCustomer();
 }
Example #23
0
 public HighloadApiLimitProvider(ISettingsService settingsService, IConnectionProvider connectionProvider)
     : base(settingsService, connectionProvider)
 {
     _dbType = connectionProvider.GetCustomer().DatabaseType;
 }
Example #24
0
 protected SettingsServiceBase(IConnectionProvider connectionProvider, ICacheProvider provider)
 {
     _customer = connectionProvider.GetCustomer();
     _provider = provider;
 }
Example #25
0
 /// <summary>
 /// конструктор
 /// </summary>
 /// <param name="connectionString">Строка подключения к TaskRunnerEntities.
 public TaskService(IConnectionProvider provider)
 {
     _provider = provider;
     _customer = _provider.GetCustomer(Service.Actions);
     _taskRm   = new ResourceManager(typeof(TaskStrings));
 }
 public LocalizationSettingsService(ISettingsService settingsService, IConnectionProvider connectionProvider)
 {
     _settingsService = settingsService;
     _customer        = connectionProvider.GetCustomer();
 }
 public ProductContentResolver(ISettingsService settingsService, IConnectionProvider connectionProvider)
 {
     _settingsService = settingsService;
     _customer        = connectionProvider.GetCustomer();
 }
 public EditorCustomActionService(IConnectionProvider connectionProvider)
 {
     _customer = connectionProvider.GetCustomer();
 }
Example #29
0
 public RegionService(VersionedCacheProviderBase cacheProvider, ISettingsService settingsService, IConnectionProvider connectionProvider)
 {
     _cacheProvider   = cacheProvider;
     _settingsService = settingsService;
     _customer        = connectionProvider.GetCustomer();
 }
Example #30
0
        public override ActionTaskResult Process(ActionContext context)
        {
            int bundleSize             = GetBundleSize();
            int maxDegreeOfParallelism = GetMaxDegreeOfParallelism();

            string[] channels = context.Parameters.GetChannels();
            bool     localize = context.Parameters.GetLocalize();

            int    marketingProductContentId = int.Parse(_settingsService.GetSetting(SettingsTitles.MARKETING_PRODUCT_CONTENT_ID));
            string productsFieldName         = _settingsService.GetSetting(SettingsTitles.MARKETING_PRODUCT_PRODUCTS_FIELD_NAME);

            Dictionary <int, int[]> articleIdsToCheckRelationsByContentId;

            int[] productIds;

            if (context.ContentItemIds == null || context.ContentItemIds.Length == 0)
            {
                productIds = DoWithLogging(
                    () => Helpers.GetAllProductIds(int.Parse(context.Parameters["site_id"]), context.ContentId, _provider.GetCustomer()),
                    "Getting all products from content {contentId}", context.ContentId
                    );

                articleIdsToCheckRelationsByContentId = new Dictionary <int, int[]>
                {
                    { context.ContentId, productIds }
                };
            }
            else
            {
                productIds = DoWithLogging(
                    () => Helpers.ExtractRegionalProductIdsFromMarketing(context.ContentItemIds, _articleService, marketingProductContentId, productsFieldName),
                    "Getting regional product ids from marketing products content {contentId} using  field {fieldName} and ids {ids}",
                    marketingProductContentId, productsFieldName, context.ContentItemIds
                    );

                articleIdsToCheckRelationsByContentId = Helpers.GetContentIds(productIds, _provider.GetCustomer());
            }

            if (productIds.Length == 0)
            {
                return(ActionTaskResult.Error(new ActionTaskResultMessage()
                {
                    ResourceClass = nameof(SendProductActionStrings),
                    ResourceName = nameof(SendProductActionStrings.NotFound),
                    Extra = string.Join(", ", context.ContentItemIds)
                }, context.ContentItemIds));
            }

            foreach (var articleIdsWithContentId in articleIdsToCheckRelationsByContentId)
            {
                var checkResult =
                    DoWithLogging(
                        () => _articleService.CheckRelationSecurity(articleIdsWithContentId.Key, articleIdsWithContentId.Value, false),
                        "Checking relation security in content {contentId} for articles {ids}",
                        articleIdsWithContentId.Key, articleIdsWithContentId.Value
                        );

                string idsstr = string.Join(", ", checkResult.Where(n => !n.Value));

                if (!string.IsNullOrEmpty(idsstr))
                {
                    return(ActionTaskResult.Error(new ActionTaskResultMessage()
                    {
                        ResourceClass = nameof(SendProductActionStrings),
                        ResourceName = nameof(SendProductActionStrings.NoRelationAccess),
                        Extra = idsstr
                    }, context.ContentItemIds));
                }
            }

            const string skipPublishingKey = "skipPublishing";

            bool skipPublishing = context.Parameters.ContainsKey(skipPublishingKey) && bool.Parse(context.Parameters[skipPublishingKey]);

            const string skipLiveKey = "skipLive";

            bool skipLive = context.Parameters.ContainsKey(skipLiveKey) && bool.Parse(context.Parameters[skipLiveKey]);

            const string ignoredStatusKey = "IgnoredStatus";

            string ignoredStatus = (context.Parameters.ContainsKey(ignoredStatusKey)) ? context.Parameters[ignoredStatusKey] : null;


            float currentPercent = 0;

            object percentLocker = new object();



            var parts = productIds.Section(bundleSize).ToArray();

            var filteredInStage            = new ConcurrentBag <int>();
            var filteredInLive             = new ConcurrentBag <int>();
            var failed                     = new ConcurrentDictionary <int, object>();
            var missing                    = new ConcurrentBag <int>();
            var excluded                   = new ConcurrentBag <int>();
            var frozen                     = new ConcurrentBag <int>();
            var invisibleOrArchivedIds     = new ConcurrentBag <int>();
            var errors                     = new ConcurrentBag <Exception>();
            var validationErrors           = new ConcurrentDictionary <int, ActionTaskResult>();
            var validationErrorsSerialized = new ConcurrentDictionary <int, string>();

            Parallel.ForEach(parts, new ParallelOptions {
                MaxDegreeOfParallelism = maxDegreeOfParallelism
            },
                             () =>
            {
                HttpContextUserProvider.ForcedUserId = context.UserId;
                return(new Local
                {
                    ProductService = ObjectFactoryBase.Resolve <IProductService>(),
                    QpNotificationService = ObjectFactoryBase.Resolve <IQPNotificationService>(),
                    XmlProductService = ObjectFactoryBase.Resolve <IXmlProductService>()
                });
            },
                             (idsToProcess, ps, tl) =>
            {
                try
                {
                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    var localInvisibleOrArchivedIds = new HashSet <int>();


                    Article[] prodsStage = DoWithLogging(
                        () => tl.ProductService.GetProductsByIds(idsToProcess.ToArray()),
                        "Getting products {ids}", idsToProcess.ToArray()
                        );
                    IEnumerable <string> ignoredStatuses = ignoredStatus?.Split(',') ??
                                                           Enumerable.Empty <string>().ToArray();
                    var excludedStage = prodsStage.Where(n => ignoredStatuses.Contains(n.Status)).ToArray();

                    foreach (var item in excludedStage)
                    {
                        excluded.Add(item.Id);
                    }

                    prodsStage = prodsStage.Except(excludedStage).ToArray();

                    var frozenIds = new int[0];

                    if (!skipLive)
                    {
                        var idsToCheck = prodsStage.Select(p => p.Id).ToArray();
                        frozenIds      = DoWithLogging(
                            () => _freezeService.GetFrozenProductIds(idsToCheck),
                            "Getting freezing state for products {ids}", idsToCheck
                            );
                    }

                    prodsStage = prodsStage.Where(p => !frozenIds.Contains(p.Id)).ToArray();

                    foreach (int id in frozenIds)
                    {
                        frozen.Add(id);
                    }

                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    //Валидация продуктов
                    foreach (int id in prodsStage.Where(w => !w.Archived && w.Visible).Select(s => s.Id))
                    {
                        var xamlValidationErrors = DoWithLogging(
                            () => _articleService.XamlValidationById(id, true),
                            "Validating XAML for product {id}", id
                            );
                        var validationResult = ActionTaskResult.FromRulesException(xamlValidationErrors, id);

                        if (!validationResult.IsSuccess)
                        {
                            validationErrors.TryAdd(id, validationResult);
                            validationErrorsSerialized.TryAdd(id, validationResult.ToString());
                        }
                    }
                    prodsStage = prodsStage.Where(w => !validationErrors.Keys.Contains(w.Id)).ToArray();

                    var prodsLive = new Article[] { };

                    if (!skipLive)
                    {
                        if (!skipPublishing)
                        {
                            prodsLive = prodsStage;
                        }
                        else
                        {
                            prodsLive = DoWithLogging(
                                () => tl.ProductService.GetProductsByIds(idsToProcess.ToArray(), true),
                                "Getting separate live products {ids}", idsToProcess.ToArray()
                                );
                        }
                    }


                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    lock (percentLocker)
                    {
                        currentPercent += (float)50 / parts.Length;
                    }

                    TaskContext.SetProgress((byte)currentPercent);

                    // архивные или невидимые продукты следует удалить с витрин
                    foreach (var product in prodsLive.Where(product => product.Archived || !product.Visible))
                    {
                        localInvisibleOrArchivedIds.Add(product.Id);
                    }

                    if (!skipLive)
                    {
                        foreach (var item in idsToProcess.Except(prodsLive.Select(y => y.Id)))
                        {
                            missing.Add(item);
                        }
                    }

                    //неопубликованные или расщепленные публикуем сразу
                    int[] prodsToPublishIds = null;

                    if (!skipPublishing)
                    {
                        prodsToPublishIds = prodsLive
                                            .Where(x =>
                                                   !x.Archived &&
                                                   x.Visible &&
                                                   (
                                                       !x.IsPublished ||
                                                       PublishAction.GetAllArticlesToCheck(x).Any(p => !p.IsPublished) ||
                                                       _freezeService.GetFreezeState(x.Id) == FreezeState.Unfrosen
                                                   )
                                                   )
                                            .Select(x => x.Id)
                                            .ToArray();

                        if (TaskContext.IsCancellationRequested)
                        {
                            TaskContext.IsCancelled = true;

                            return(tl);
                        }

                        // удалим требующие публикации или удаления продукты
                        prodsLive = prodsLive
                                    .Where(p => !prodsToPublishIds.Contains(p.Id) && !localInvisibleOrArchivedIds.Contains(p.Id))
                                    .ToArray();
                    }


                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    lock (percentLocker)
                    {
                        currentPercent += (float)30 / parts.Length;
                    }

                    TaskContext.SetProgress((byte)currentPercent);

                    foreach (var id in localInvisibleOrArchivedIds)
                    {
                        invisibleOrArchivedIds.Add(id);
                    }

                    int sectionSize = Math.Min(bundleSize, 5);

                    var tasks =
                        ArticleFilter.LiveFilter.Filter(prodsLive)
                        .Section(sectionSize)
                        .Select(z => tl.QpNotificationService
                                .SendProductsAsync(z.ToArray(), false, context.UserName, context.UserId,
                                                   localize, false, channels)
                                .ContinueWith(y => UpdateFilteredIds(filteredInLive,
                                                                     y.IsFaulted ? null : y.Result, z, y.Exception, errors, failed)))
                        .Concat(ArticleFilter.DefaultFilter.Filter(prodsStage)
                                .Section(sectionSize)
                                .Select(z => tl.QpNotificationService.SendProductsAsync(z.ToArray(), true,
                                                                                        context.UserName, context.UserId, localize, false, channels)
                                        .ContinueWith(y => UpdateFilteredIds(filteredInStage,
                                                                             y.IsFaulted ? null : y.Result, z, y.Exception, errors, failed))))
                        .ToArray();



                    if (tasks.Length > 0)
                    {
                        float percentsPerTask = (float)10 / parts.Length / tasks.Length;

                        tasks = tasks
                                .Select(x => x.ContinueWith(y =>
                        {
                            lock (percentLocker)
                            {
                                currentPercent += percentsPerTask;
                            }
                            TaskContext.SetProgress((byte)currentPercent);
                        }))
                                .ToArray();

                        DoWithLogging(() => Task.WaitAll(tasks),
                                      "Sending notifications for live ({liveIds}) and stage ({stageIds}) products",
                                      ArticleFilter.LiveFilter.Filter(prodsLive).Select(n => n.Id).ToArray(),
                                      ArticleFilter.DefaultFilter.Filter(prodsStage).Select(n => n.Id).ToArray()
                                      );
                    }
                    else
                    {
                        lock (percentLocker)
                        {
                            currentPercent += (float)10 / parts.Length;
                        }
                        TaskContext.SetProgress((byte)currentPercent);
                    }

                    if (TaskContext.IsCancellationRequested)
                    {
                        TaskContext.IsCancelled = true;

                        return(tl);
                    }

                    // эти продукты имеют неопубликованные или расщепленные статьи
                    if (!skipPublishing && prodsToPublishIds.Length > 0)
                    {
                        var publishAction = ObjectFactoryBase.Resolve <PublishAction>();

                        var publishActionContext = new ActionContext
                        {
                            ContentItemIds = prodsToPublishIds,
                            Parameters     = new Dictionary <string, string>()
                            {
                                { ignoredStatusKey, ignoredStatus }
                            },
                            UserId   = context.UserId,
                            UserName = context.UserName
                        };

                        try
                        {
                            DoWithLogging(
                                () => publishAction.Process(publishActionContext),
                                "Calling PublishAction for products {ids}",
                                prodsToPublishIds
                                );
                        }
                        catch (ActionException ex)
                        {
                            var ids = ex.InnerExceptions.OfType <ProductException>().Select(x => x.ProductId);
                            Logger.Error()
                            .Exception(ex)
                            .Message("Exception has been thrown while publishing products {ids}", prodsToPublishIds)
                            .Write();

                            foreach (var pID in ids)
                            {
                                failed.TryAdd(pID, null);
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error()
                            .Exception(ex)
                            .Message("Exception has been thrown while publishing products {ids}", prodsToPublishIds)
                            .Write();
                        }
                    }

                    lock (percentLocker)
                    {
                        currentPercent += (float)10 / parts.Length;
                    }

                    TaskContext.SetProgress((byte)currentPercent);

                    return(tl);
                }
                catch (Exception ex)
                {
                    Logger.Error().Message("SendProductAction exception").Exception(ex).Write();

                    foreach (var item in idsToProcess)
                    {
                        failed.TryAdd(item, null);
                    }

                    errors.Add(ex);
                }

                HttpContextUserProvider.ForcedUserId = 0;
                return(tl);
            }, tt => { });

            if (TaskContext.IsCancellationRequested)
            {
                TaskContext.IsCancelled = true;

                return(ActionTaskResult.Error(new ActionTaskResultMessage()
                {
                    ResourceClass = nameof(SendProductActionStrings),
                    ResourceName = nameof(SendProductActionStrings.Cancelled)
                }, context.ContentItemIds));
            }

            var productsToRemove      = new int[0];
            var productsToRemoveCheck = missing
                                        .Concat(invisibleOrArchivedIds)
                                        .Except(excluded)
                                        .Except(frozen)
                                        .Except(validationErrors.Keys)
                                        .ToArray();

            if (productsToRemoveCheck.Length > 0)
            {
                // проверяем, какие из проблемных продуктов присутствуют на витрине
                var cmService = ObjectFactoryBase.Resolve <IList <IConsumerMonitoringService> >();

                productsToRemove = DoWithLogging(
                    () => cmService.SelectMany(s => s.FindExistingProducts(productsToRemoveCheck)).Distinct().ToArray(),
                    "Checking whether products {ids} are missing on fronts", productsToRemoveCheck
                    );

                if (productsToRemove.Length > 0)
                {
                    // эти продукты отсутствуют в DPC или не видны, но остались на витрине
                    // их надо удалить с витрин
                    var service        = ObjectFactoryBase.Resolve <IQPNotificationService>();
                    var productService = ObjectFactoryBase.Resolve <IProductService>();
                    DoWithLogging(
                        () => Task.WhenAll(productsToRemove.Section(20).Select(
                                               s => service.DeleteProductsAsync(
                                                   productService.GetSimpleProductsByIds(s.ToArray()),
                                                   context.UserName,
                                                   context.UserId,
                                                   false)
                                               )
                                           ).Wait(),
                        "Removing missing products from fronts {ids}", productsToRemove
                        );
                }
            }

            DoWithLogging(
                () => _validationService.UpdateValidationInfo(productIds, validationErrorsSerialized),
                "Updating validation info for products {ids}", productIds
                );

            int[] notFound = missing.Except(productsToRemove).Except(excluded).Except(frozen).Except(validationErrors.Keys).ToArray();

            var notSucceeded = failed.Keys.Concat(notFound).Concat(excluded).Concat(frozen)
                               .Concat(validationErrors.Keys).ToArray();

            var result = new ActionTaskResult()
            {
                FailedIds = notSucceeded
            };

            var msg = new ActionTaskResultMessage()
            {
                ResourceClass = nameof(SendProductActionStrings)
            };

            if (notSucceeded.Any())
            {
                msg.ResourceName = nameof(SendProductActionStrings.PartiallySucceededResult);
                msg.Extra        = string.Join(", ", notSucceeded);
                msg.Parameters   = new object[] { productIds.Length - notSucceeded.Length, productIds.Length };
            }

            else
            {
                msg.ResourceName = nameof(SendProductActionStrings.SucceededResult);
                msg.Parameters   = new object[] { productIds.Length };
            }

            result.Messages.Add(msg);

            if (errors.Any())
            {
                result.Messages.Add(new ActionTaskResultMessage()
                {
                    ResourceClass = nameof(SendProductActionStrings),
                    ResourceName  = nameof(SendProductActionStrings.Errors),
                    Extra         = string.Join(", ", errors.Select(x => x.Message).Distinct())
                });
            }

            AddMessages(result, nameof(SendProductActionStrings.ExcludedByStatus), excluded.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.ExcludedWithFreezing), frozen.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.NotFoundInDpc), notFound.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.RemovedFromFronts), productsToRemove.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.NotPassedByStageFiltration), filteredInStage.ToArray());
            AddMessages(result, nameof(SendProductActionStrings.NotPassedByLiveFiltration), filteredInLive.ToArray());

            if (validationErrors.Any())
            {
                result.Messages.AddRange(validationErrors.SelectMany(v => v.Value.Messages));
            }

            TaskContext.Result = result;

            return(result);
        }