Make the indexing batch size configurable (#20543)
* Introduce configurable batch size for indexing * Stop using Examine indexing events for reporting index rebuild operation completeness (it is volatile)
This commit is contained in:
@@ -9,10 +9,16 @@ namespace Umbraco.Cms.Core.Configuration.Models;
|
||||
public class IndexingSettings
|
||||
{
|
||||
private const bool StaticExplicitlyIndexEachNestedProperty = false;
|
||||
private const int StaticBatchSize = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value for whether each nested property should have it's own indexed value. Requires a rebuild of indexes when changed.
|
||||
/// </summary>
|
||||
[DefaultValue(StaticExplicitlyIndexEachNestedProperty)]
|
||||
public bool ExplicitlyIndexEachNestedProperty { get; set; } = StaticExplicitlyIndexEachNestedProperty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value for how many items to index at a time.
|
||||
/// </summary>
|
||||
public int BatchSize { get; set; } = StaticBatchSize;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
@@ -20,11 +24,23 @@ public class ContentIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
private readonly bool _publishedValuesOnly;
|
||||
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
|
||||
|
||||
private IndexingSettings _indexingSettings;
|
||||
|
||||
/// <summary>
|
||||
/// This is a static query, it's parameters don't change so store statically
|
||||
/// </summary>
|
||||
private IQuery<IContent>? _publishedQuery;
|
||||
|
||||
[Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
|
||||
public ContentIndexPopulator(
|
||||
ILogger<ContentIndexPopulator> logger,
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IContentValueSetBuilder contentValueSetBuilder)
|
||||
: this(logger, false, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor to lookup all content data
|
||||
/// </summary>
|
||||
@@ -32,8 +48,21 @@ public class ContentIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
ILogger<ContentIndexPopulator> logger,
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IContentValueSetBuilder contentValueSetBuilder)
|
||||
: this(logger, false, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder)
|
||||
IContentValueSetBuilder contentValueSetBuilder,
|
||||
IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
: this(logger, false, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder, indexingSettings)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
|
||||
public ContentIndexPopulator(
|
||||
ILogger<ContentIndexPopulator> logger,
|
||||
bool publishedValuesOnly,
|
||||
int? parentId,
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IValueSetBuilder<IContent> contentValueSetBuilder)
|
||||
: this(logger, publishedValuesOnly, parentId, contentService, umbracoDatabaseFactory, contentValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -46,7 +75,8 @@ public class ContentIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
int? parentId,
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IValueSetBuilder<IContent> contentValueSetBuilder)
|
||||
IValueSetBuilder<IContent> contentValueSetBuilder,
|
||||
IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
{
|
||||
_contentService = contentService ?? throw new ArgumentNullException(nameof(contentService));
|
||||
_umbracoDatabaseFactory = umbracoDatabaseFactory ?? throw new ArgumentNullException(nameof(umbracoDatabaseFactory));
|
||||
@@ -54,6 +84,12 @@ public class ContentIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_publishedValuesOnly = publishedValuesOnly;
|
||||
_parentId = parentId;
|
||||
_indexingSettings = indexingSettings.CurrentValue;
|
||||
|
||||
indexingSettings.OnChange(change =>
|
||||
{
|
||||
_indexingSettings = change;
|
||||
});
|
||||
}
|
||||
|
||||
private IQuery<IContent> PublishedQuery => _publishedQuery ??=
|
||||
@@ -75,7 +111,6 @@ public class ContentIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
return;
|
||||
}
|
||||
|
||||
const int pageSize = 10000;
|
||||
var pageIndex = 0;
|
||||
|
||||
var contentParentId = -1;
|
||||
@@ -86,11 +121,11 @@ public class ContentIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
|
||||
if (_publishedValuesOnly)
|
||||
{
|
||||
IndexPublishedContent(contentParentId, pageIndex, pageSize, indexes);
|
||||
IndexPublishedContent(contentParentId, pageIndex, _indexingSettings.BatchSize, indexes);
|
||||
}
|
||||
else
|
||||
{
|
||||
IndexAllContent(contentParentId, pageIndex, pageSize, indexes);
|
||||
IndexAllContent(contentParentId, pageIndex, _indexingSettings.BatchSize, indexes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
@@ -14,22 +16,33 @@ internal sealed class DeliveryApiContentIndexHelper : IDeliveryApiContentIndexHe
|
||||
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
|
||||
private DeliveryApiSettings _deliveryApiSettings;
|
||||
|
||||
private IndexingSettings _indexingSettings;
|
||||
|
||||
[Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
|
||||
public DeliveryApiContentIndexHelper(
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IOptionsMonitor<DeliveryApiSettings> deliveryApiSettings)
|
||||
: this(contentService, umbracoDatabaseFactory, deliveryApiSettings, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
|
||||
{
|
||||
}
|
||||
|
||||
public DeliveryApiContentIndexHelper(
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IOptionsMonitor<DeliveryApiSettings> deliveryApiSettings,
|
||||
IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
{
|
||||
_contentService = contentService;
|
||||
_umbracoDatabaseFactory = umbracoDatabaseFactory;
|
||||
_deliveryApiSettings = deliveryApiSettings.CurrentValue;
|
||||
_indexingSettings = indexingSettings.CurrentValue;
|
||||
deliveryApiSettings.OnChange(settings => _deliveryApiSettings = settings);
|
||||
indexingSettings.OnChange(settings => _indexingSettings = settings);
|
||||
}
|
||||
|
||||
public void EnumerateApplicableDescendantsForContentIndex(int rootContentId, Action<IContent[]> actionToPerform)
|
||||
{
|
||||
const int pageSize = 10000;
|
||||
EnumerateApplicableDescendantsForContentIndex(rootContentId, actionToPerform, pageSize);
|
||||
}
|
||||
=> EnumerateApplicableDescendantsForContentIndex(rootContentId, actionToPerform, _indexingSettings.BatchSize);
|
||||
|
||||
internal void EnumerateApplicableDescendantsForContentIndex(int rootContentId, Action<IContent[]> actionToPerform, int pageSize)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
|
||||
@@ -15,23 +19,43 @@ public class MediaIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
private readonly IValueSetBuilder<IMedia> _mediaValueSetBuilder;
|
||||
private readonly int? _parentId;
|
||||
|
||||
private IndexingSettings _indexingSettings;
|
||||
|
||||
[Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
|
||||
public MediaIndexPopulator(ILogger<MediaIndexPopulator> logger, IMediaService mediaService, IValueSetBuilder<IMedia> mediaValueSetBuilder)
|
||||
: this(logger, null, mediaService, mediaValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor to lookup all content data
|
||||
/// </summary>
|
||||
public MediaIndexPopulator(ILogger<MediaIndexPopulator> logger, IMediaService mediaService, IValueSetBuilder<IMedia> mediaValueSetBuilder)
|
||||
: this(logger, null, mediaService, mediaValueSetBuilder)
|
||||
public MediaIndexPopulator(ILogger<MediaIndexPopulator> logger, IMediaService mediaService, IValueSetBuilder<IMedia> mediaValueSetBuilder, IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
: this(logger, null, mediaService, mediaValueSetBuilder, indexingSettings)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
|
||||
public MediaIndexPopulator(ILogger<MediaIndexPopulator> logger, int? parentId, IMediaService mediaService, IValueSetBuilder<IMedia> mediaValueSetBuilder)
|
||||
: this(logger, parentId, mediaService, mediaValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<IndexingSettings>>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional constructor allowing specifying custom query parameters
|
||||
/// </summary>
|
||||
public MediaIndexPopulator(ILogger<MediaIndexPopulator> logger, int? parentId, IMediaService mediaService, IValueSetBuilder<IMedia> mediaValueSetBuilder)
|
||||
public MediaIndexPopulator(ILogger<MediaIndexPopulator> logger, int? parentId, IMediaService mediaService, IValueSetBuilder<IMedia> mediaValueSetBuilder, IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
{
|
||||
_logger = logger;
|
||||
_parentId = parentId;
|
||||
_mediaService = mediaService;
|
||||
_mediaValueSetBuilder = mediaValueSetBuilder;
|
||||
_indexingSettings = indexingSettings.CurrentValue;
|
||||
|
||||
indexingSettings.OnChange(change =>
|
||||
{
|
||||
_indexingSettings = change;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)
|
||||
@@ -46,7 +70,6 @@ public class MediaIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
return;
|
||||
}
|
||||
|
||||
const int pageSize = 10000;
|
||||
var pageIndex = 0;
|
||||
|
||||
var mediaParentId = -1;
|
||||
@@ -60,7 +83,7 @@ public class MediaIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
|
||||
do
|
||||
{
|
||||
media = _mediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out _).ToArray();
|
||||
media = _mediaService.GetPagedDescendants(mediaParentId, pageIndex, _indexingSettings.BatchSize, out _).ToArray();
|
||||
|
||||
// ReSharper disable once PossibleMultipleEnumeration
|
||||
foreach (IIndex index in indexes)
|
||||
@@ -70,6 +93,6 @@ public class MediaIndexPopulator : IndexPopulator<IUmbracoContentIndex>
|
||||
|
||||
pageIndex++;
|
||||
}
|
||||
while (media.Length == pageSize);
|
||||
while (media.Length == _indexingSettings.BatchSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
@@ -15,6 +17,7 @@ namespace Umbraco.Cms.Infrastructure.Examine;
|
||||
/// </remarks>
|
||||
public class PublishedContentIndexPopulator : ContentIndexPopulator
|
||||
{
|
||||
[Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
|
||||
public PublishedContentIndexPopulator(
|
||||
ILogger<PublishedContentIndexPopulator> logger,
|
||||
IContentService contentService,
|
||||
@@ -23,4 +26,14 @@ public class PublishedContentIndexPopulator : ContentIndexPopulator
|
||||
: base(logger, true, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder)
|
||||
{
|
||||
}
|
||||
|
||||
public PublishedContentIndexPopulator(
|
||||
ILogger<PublishedContentIndexPopulator> logger,
|
||||
IContentService contentService,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IPublishedContentValueSetBuilder contentValueSetBuilder,
|
||||
IOptionsMonitor<IndexingSettings> indexingSettings)
|
||||
: base(logger, true, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder, indexingSettings)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,6 @@ public class IndexingRebuilderService : IIndexingRebuilderService
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> TryRebuildAsync(IIndex index, string indexName)
|
||||
{
|
||||
// Remove it in case there's a handler there already
|
||||
index.IndexOperationComplete -= Indexer_IndexOperationComplete;
|
||||
|
||||
// Now add a single handler
|
||||
index.IndexOperationComplete += Indexer_IndexOperationComplete;
|
||||
|
||||
try
|
||||
{
|
||||
Attempt<IndexRebuildResult> attempt = await _indexRebuilder.RebuildIndexAsync(indexName);
|
||||
@@ -55,8 +49,6 @@ public class IndexingRebuilderService : IIndexingRebuilderService
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// Ensure it's not listening
|
||||
index.IndexOperationComplete -= Indexer_IndexOperationComplete;
|
||||
_logger.LogError(exception, "An error occurred rebuilding index");
|
||||
return false;
|
||||
}
|
||||
@@ -70,19 +62,4 @@ public class IndexingRebuilderService : IIndexingRebuilderService
|
||||
/// <inheritdoc />
|
||||
public Task<bool> IsRebuildingAsync(string indexName)
|
||||
=> _indexRebuilder.IsRebuildingAsync(indexName);
|
||||
|
||||
private void Indexer_IndexOperationComplete(object? sender, EventArgs e)
|
||||
{
|
||||
var indexer = (IIndex?)sender;
|
||||
|
||||
_logger.LogDebug("Logging operation completed for index {IndexName}", indexer?.Name);
|
||||
|
||||
if (indexer is not null)
|
||||
{
|
||||
//ensure it's not listening anymore
|
||||
indexer.IndexOperationComplete -= Indexer_IndexOperationComplete;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Rebuilding index '{IndexerName}' done.", indexer?.Name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public class IndexInitializer
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly IDocumentUrlService _documentUrlService;
|
||||
private readonly ILanguageService _languageService;
|
||||
private readonly IOptionsMonitor<IndexingSettings> _indexSettings;
|
||||
|
||||
public IndexInitializer(
|
||||
IShortStringHelper shortStringHelper,
|
||||
@@ -50,7 +51,8 @@ public class IndexInitializer
|
||||
ILocalizationService localizationService,
|
||||
IContentTypeService contentTypeService,
|
||||
IDocumentUrlService documentUrlService,
|
||||
ILanguageService languageService)
|
||||
ILanguageService languageService,
|
||||
IOptionsMonitor<IndexingSettings> indexSettings)
|
||||
{
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_propertyEditors = propertyEditors;
|
||||
@@ -62,6 +64,7 @@ public class IndexInitializer
|
||||
_contentTypeService = contentTypeService;
|
||||
_documentUrlService = documentUrlService;
|
||||
_languageService = languageService;
|
||||
_indexSettings = indexSettings;
|
||||
}
|
||||
|
||||
public ContentValueSetBuilder GetContentValueSetBuilder(bool publishedValuesOnly)
|
||||
@@ -91,7 +94,8 @@ public class IndexInitializer
|
||||
null,
|
||||
contentService,
|
||||
umbracoDatabaseFactory,
|
||||
contentValueSetBuilder);
|
||||
contentValueSetBuilder,
|
||||
_indexSettings);
|
||||
return contentIndexDataSource;
|
||||
}
|
||||
|
||||
@@ -105,7 +109,7 @@ public class IndexInitializer
|
||||
_shortStringHelper,
|
||||
_contentSettings,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>());
|
||||
var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder);
|
||||
var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder, _indexSettings);
|
||||
return mediaIndexDataSource;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user