Exemple #1
0
        protected virtual async Task <IndexingResult> ProcessPartialDocumentsAsync(
            IEnumerable <IndexDocumentChange> changes,
            BatchIndexingOptions batchOptions,
            ICancellationToken cancellationToken)
        {
            var result = new IndexingResult {
                Items = new List <IndexingResultItem>()
            };

            var indexDocumentChanges = changes as IndexDocumentChange[] ?? changes.ToArray();

            var changeIds = indexDocumentChanges.Select(x => x.DocumentId).Distinct();

            foreach (var id in changeIds)
            {
                var builders = indexDocumentChanges
                               .Where(x => x.DocumentId == id)
                               .SelectMany(x => _configs.GetBuildersForProvider(x.Provider.GetType()));

                var documents = await GetDocumentsAsync(new[] { id }, null, builders, cancellationToken);

                IndexingResult indexingResult;

                indexingResult = await((ISupportPartialUpdate)_searchProvider).IndexPartialAsync(batchOptions.DocumentType, documents);

                result.Items.AddRange(indexingResult.Items);
            }

            return(result);
        }
Exemple #2
0
        protected virtual async Task <IndexingResult> ProcessChangesAsync(IEnumerable <IndexDocumentChange> changes,
                                                                          BatchIndexingOptions batchOptions, ICancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var result = new IndexingResult {
                Items = new List <IndexingResultItem>()
            };

            var indexDocumentChanges = changes as IndexDocumentChange[] ?? changes.ToArray();

            // Full changes don't have changes provider specified because we don't set it for manual indexation.
            var fullChanges = _searchProvider is ISupportPartialUpdate?indexDocumentChanges
                              .Where(x =>
                                     x.ChangeType is IndexDocumentChangeType.Deleted or IndexDocumentChangeType.Created ||
                                     !_configs.GetBuildersForProvider(x.Provider?.GetType()).Any()
                                     )
                              .ToArray() : indexDocumentChanges;

            var partialChanges = indexDocumentChanges.Except(fullChanges);

            var partialResult = await ProcessPartialDocumentsAsync(partialChanges, batchOptions, cancellationToken);

            var groups = GetLatestChangesForEachDocumentGroupedByChangeType(fullChanges);

            foreach (var group in groups)
            {
                var changeType   = group.Key;
                var changesGroup = group.Value;

                var groupResult =
                    await ProcessDocumentsAsync(changeType, changesGroup, batchOptions, cancellationToken);

                if (groupResult?.Items != null)
                {
                    result.Items.AddRange(groupResult.Items);
                }
            }

            result.Items.AddRange(partialResult.Items);

            return(result);
        }
Exemple #3
0
        protected virtual async Task <IndexingResult> ProcessDocumentsAsync(IndexDocumentChangeType changeType, IList <string> documentIds, BatchIndexingOptions batchOptions, ICancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            IndexingResult result = null;

            if (changeType == IndexDocumentChangeType.Deleted)
            {
                result = await DeleteDocumentsAsync(batchOptions.DocumentType, documentIds.ToArray());
            }
            else if (changeType == IndexDocumentChangeType.Modified)
            {
                result = await IndexDocumentsAsync(batchOptions.DocumentType, documentIds, batchOptions.PrimaryDocumentBuilder, batchOptions.SecondaryDocumentBuilders, cancellationToken);
            }

            return(result);
        }
Exemple #4
0
        protected virtual async Task <IndexingResult> ProcessChangesAsync(IEnumerable <IndexDocumentChange> changes, BatchIndexingOptions batchOptions, ICancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var result = new IndexingResult();

            var groups = GetLatestChangesForEachDocumentGroupedByChangeType(changes);

            foreach (var group in groups)
            {
                var changeType  = group.Key;
                var documentIds = group.Value;

                var groupResult = await ProcessDocumentsAsync(changeType, documentIds, batchOptions, cancellationToken);

                if (groupResult?.Items != null)
                {
                    if (result.Items == null)
                    {
                        result.Items = new List <IndexingResultItem>();
                    }

                    result.Items.AddRange(groupResult.Items);
                }
            }

            return(result);
        }
Exemple #5
0
        protected virtual async Task ProcessConfigurationAsync(IndexDocumentConfiguration configuration, IndexingOptions options, Action <IndexingProgress> progressCallback, ICancellationToken cancellationToken)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }
            if (string.IsNullOrEmpty(configuration.DocumentType))
            {
                throw new ArgumentNullException($"{nameof(configuration)}.{nameof(configuration.DocumentType)}");
            }
            if (configuration.DocumentSource == null)
            {
                throw new ArgumentNullException($"{nameof(configuration)}.{nameof(configuration.DocumentSource)}");
            }
            if (configuration.DocumentSource.ChangesProvider == null)
            {
                throw new ArgumentNullException($"{nameof(configuration)}.{nameof(configuration.DocumentSource)}.{nameof(configuration.DocumentSource.ChangesProvider)}");
            }
            if (configuration.DocumentSource.DocumentBuilder == null)
            {
                throw new ArgumentNullException($"{nameof(configuration)}.{nameof(configuration.DocumentSource)}.{nameof(configuration.DocumentSource.DocumentBuilder)}");
            }

            cancellationToken.ThrowIfCancellationRequested();

            var documentType = options.DocumentType;

            progressCallback?.Invoke(new IndexingProgress($"{documentType}: calculating total count", documentType));

            var batchOptions = new BatchIndexingOptions
            {
                DocumentType              = options.DocumentType,
                PrimaryDocumentBuilder    = configuration.DocumentSource.DocumentBuilder,
                SecondaryDocumentBuilders = configuration.RelatedSources
                                            ?.Where(s => s.DocumentBuilder != null)
                                            .Select(s => s.DocumentBuilder)
                                            .ToList(),
            };

            var feeds = await GetChangeFeeds(configuration, options);

            // Try to get total count to indicate progress. Some feeds don't have a total count.
            var totalCount = feeds.Any(x => x.TotalCount == null)
                ? (long?)null
                : feeds.Sum(x => x.TotalCount ?? 0);

            long processedCount = 0;

            var changes = await GetNextChangesAsync(feeds);

            while (changes.Any())
            {
                IList <string> errors = null;

                if (_backgroundWorker == null)
                {
                    var indexingResult = await ProcessChangesAsync(changes, batchOptions, cancellationToken);

                    errors = GetIndexingErrors(indexingResult);
                }
                else
                {
                    // We're executing a job to index all documents or the changes since a specific time.
                    // Priority for this indexation work should be quite low.
                    var documentIds = changes
                                      .Select(x => x.DocumentId)
                                      .Distinct()
                                      .ToArray();

                    _backgroundWorker.IndexDocuments(configuration.DocumentType, documentIds, IndexingPriority.Background);
                }

                processedCount += changes.Count;

                var description = totalCount != null
                    ? $"{documentType}: {processedCount} of {totalCount} have been indexed"
                    : $"{documentType}: {processedCount} have been indexed";

                progressCallback?.Invoke(new IndexingProgress(description, documentType, totalCount, processedCount, errors));

                changes = await GetNextChangesAsync(feeds);
            }

            progressCallback?.Invoke(new IndexingProgress($"{documentType}: indexation finished", documentType, totalCount ?? processedCount, processedCount));
        }
Exemple #6
0
        protected virtual async Task <IndexingResult> ProcessDocumentsAsync(IndexDocumentChangeType changeType,
                                                                            string[] changedIds, BatchIndexingOptions batchOptions, ICancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            IndexingResult result = null;

            if (changeType == IndexDocumentChangeType.Deleted)
            {
                result = await DeleteDocumentsAsync(batchOptions.DocumentType, changedIds);
            }
            else if (changeType is IndexDocumentChangeType.Modified or IndexDocumentChangeType.Created)
            {
                var documents = await GetDocumentsAsync(changedIds, batchOptions.PrimaryDocumentBuilder, batchOptions.SecondaryDocumentBuilders, cancellationToken);

                if (batchOptions.Reindex && _searchProvider is ISupportIndexSwap supportIndexSwapProvider)
                {
                    result = await supportIndexSwapProvider.IndexWithBackupAsync(batchOptions.DocumentType, documents);
                }
                else
                {
                    result = await _searchProvider.IndexAsync(batchOptions.DocumentType, documents);
                }
            }

            return(result);
        }