diff --git a/src/Umbraco.Core/Configuration/Models/IndexingSettings.cs b/src/Umbraco.Core/Configuration/Models/IndexingSettings.cs
index ff3bebd989..282d6c57fb 100644
--- a/src/Umbraco.Core/Configuration/Models/IndexingSettings.cs
+++ b/src/Umbraco.Core/Configuration/Models/IndexingSettings.cs
@@ -9,10 +9,16 @@ namespace Umbraco.Cms.Core.Configuration.Models;
public class IndexingSettings
{
private const bool StaticExplicitlyIndexEachNestedProperty = false;
+ private const int StaticBatchSize = 10000;
///
/// Gets or sets a value for whether each nested property should have it's own indexed value. Requires a rebuild of indexes when changed.
///
[DefaultValue(StaticExplicitlyIndexEachNestedProperty)]
public bool ExplicitlyIndexEachNestedProperty { get; set; } = StaticExplicitlyIndexEachNestedProperty;
+
+ ///
+ /// Gets or sets a value for how many items to index at a time.
+ ///
+ public int BatchSize { get; set; } = StaticBatchSize;
}
diff --git a/src/Umbraco.Infrastructure/Examine/ContentIndexPopulator.cs b/src/Umbraco.Infrastructure/Examine/ContentIndexPopulator.cs
index eb9e9f135f..e912728fee 100644
--- a/src/Umbraco.Infrastructure/Examine/ContentIndexPopulator.cs
+++ b/src/Umbraco.Infrastructure/Examine/ContentIndexPopulator.cs
@@ -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
private readonly bool _publishedValuesOnly;
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
+ private IndexingSettings _indexingSettings;
+
///
/// This is a static query, it's parameters don't change so store statically
///
private IQuery? _publishedQuery;
+ [Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
+ public ContentIndexPopulator(
+ ILogger logger,
+ IContentService contentService,
+ IUmbracoDatabaseFactory umbracoDatabaseFactory,
+ IContentValueSetBuilder contentValueSetBuilder)
+ : this(logger, false, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService>())
+ {
+ }
+
///
/// Default constructor to lookup all content data
///
@@ -32,8 +48,21 @@ public class ContentIndexPopulator : IndexPopulator
ILogger logger,
IContentService contentService,
IUmbracoDatabaseFactory umbracoDatabaseFactory,
- IContentValueSetBuilder contentValueSetBuilder)
- : this(logger, false, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder)
+ IContentValueSetBuilder contentValueSetBuilder,
+ IOptionsMonitor indexingSettings)
+ : this(logger, false, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder, indexingSettings)
+ {
+ }
+
+ [Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
+ public ContentIndexPopulator(
+ ILogger logger,
+ bool publishedValuesOnly,
+ int? parentId,
+ IContentService contentService,
+ IUmbracoDatabaseFactory umbracoDatabaseFactory,
+ IValueSetBuilder contentValueSetBuilder)
+ : this(logger, publishedValuesOnly, parentId, contentService, umbracoDatabaseFactory, contentValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService>())
{
}
@@ -46,7 +75,8 @@ public class ContentIndexPopulator : IndexPopulator
int? parentId,
IContentService contentService,
IUmbracoDatabaseFactory umbracoDatabaseFactory,
- IValueSetBuilder contentValueSetBuilder)
+ IValueSetBuilder contentValueSetBuilder,
+ IOptionsMonitor indexingSettings)
{
_contentService = contentService ?? throw new ArgumentNullException(nameof(contentService));
_umbracoDatabaseFactory = umbracoDatabaseFactory ?? throw new ArgumentNullException(nameof(umbracoDatabaseFactory));
@@ -54,6 +84,12 @@ public class ContentIndexPopulator : IndexPopulator
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_publishedValuesOnly = publishedValuesOnly;
_parentId = parentId;
+ _indexingSettings = indexingSettings.CurrentValue;
+
+ indexingSettings.OnChange(change =>
+ {
+ _indexingSettings = change;
+ });
}
private IQuery PublishedQuery => _publishedQuery ??=
@@ -75,7 +111,6 @@ public class ContentIndexPopulator : IndexPopulator
return;
}
- const int pageSize = 10000;
var pageIndex = 0;
var contentParentId = -1;
@@ -86,11 +121,11 @@ public class ContentIndexPopulator : IndexPopulator
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);
}
}
diff --git a/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexHelper.cs b/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexHelper.cs
index d7f2fc0c69..2747773e11 100644
--- a/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexHelper.cs
+++ b/src/Umbraco.Infrastructure/Examine/DeliveryApiContentIndexHelper.cs
@@ -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)
+ : this(contentService, umbracoDatabaseFactory, deliveryApiSettings, StaticServiceProvider.Instance.GetRequiredService>())
+ {
+ }
+
+ public DeliveryApiContentIndexHelper(
+ IContentService contentService,
+ IUmbracoDatabaseFactory umbracoDatabaseFactory,
+ IOptionsMonitor deliveryApiSettings,
+ IOptionsMonitor 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 actionToPerform)
- {
- const int pageSize = 10000;
- EnumerateApplicableDescendantsForContentIndex(rootContentId, actionToPerform, pageSize);
- }
+ => EnumerateApplicableDescendantsForContentIndex(rootContentId, actionToPerform, _indexingSettings.BatchSize);
internal void EnumerateApplicableDescendantsForContentIndex(int rootContentId, Action actionToPerform, int pageSize)
{
diff --git a/src/Umbraco.Infrastructure/Examine/MediaIndexPopulator.cs b/src/Umbraco.Infrastructure/Examine/MediaIndexPopulator.cs
index 6f4a4db4a3..b9872da5c8 100644
--- a/src/Umbraco.Infrastructure/Examine/MediaIndexPopulator.cs
+++ b/src/Umbraco.Infrastructure/Examine/MediaIndexPopulator.cs
@@ -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
private readonly IValueSetBuilder _mediaValueSetBuilder;
private readonly int? _parentId;
+ private IndexingSettings _indexingSettings;
+
+ [Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
+ public MediaIndexPopulator(ILogger logger, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder)
+ : this(logger, null, mediaService, mediaValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService>())
+ {
+ }
+
///
/// Default constructor to lookup all content data
///
- public MediaIndexPopulator(ILogger logger, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder)
- : this(logger, null, mediaService, mediaValueSetBuilder)
+ public MediaIndexPopulator(ILogger logger, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder, IOptionsMonitor indexingSettings)
+ : this(logger, null, mediaService, mediaValueSetBuilder, indexingSettings)
+ {
+ }
+
+ [Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
+ public MediaIndexPopulator(ILogger logger, int? parentId, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder)
+ : this(logger, parentId, mediaService, mediaValueSetBuilder, StaticServiceProvider.Instance.GetRequiredService>())
{
}
///
/// Optional constructor allowing specifying custom query parameters
///
- public MediaIndexPopulator(ILogger logger, int? parentId, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder)
+ public MediaIndexPopulator(ILogger logger, int? parentId, IMediaService mediaService, IValueSetBuilder mediaValueSetBuilder, IOptionsMonitor indexingSettings)
{
_logger = logger;
_parentId = parentId;
_mediaService = mediaService;
_mediaValueSetBuilder = mediaValueSetBuilder;
+ _indexingSettings = indexingSettings.CurrentValue;
+
+ indexingSettings.OnChange(change =>
+ {
+ _indexingSettings = change;
+ });
}
protected override void PopulateIndexes(IReadOnlyList indexes)
@@ -46,7 +70,6 @@ public class MediaIndexPopulator : IndexPopulator
return;
}
- const int pageSize = 10000;
var pageIndex = 0;
var mediaParentId = -1;
@@ -60,7 +83,7 @@ public class MediaIndexPopulator : IndexPopulator
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
pageIndex++;
}
- while (media.Length == pageSize);
+ while (media.Length == _indexingSettings.BatchSize);
}
}
diff --git a/src/Umbraco.Infrastructure/Examine/PublishedContentIndexPopulator.cs b/src/Umbraco.Infrastructure/Examine/PublishedContentIndexPopulator.cs
index 67d59d02d9..4f07a7283f 100644
--- a/src/Umbraco.Infrastructure/Examine/PublishedContentIndexPopulator.cs
+++ b/src/Umbraco.Infrastructure/Examine/PublishedContentIndexPopulator.cs
@@ -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;
///
public class PublishedContentIndexPopulator : ContentIndexPopulator
{
+ [Obsolete("Please use the non-obsolete constructor. Scheduled for removal in V19.")]
public PublishedContentIndexPopulator(
ILogger logger,
IContentService contentService,
@@ -23,4 +26,14 @@ public class PublishedContentIndexPopulator : ContentIndexPopulator
: base(logger, true, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder)
{
}
+
+ public PublishedContentIndexPopulator(
+ ILogger logger,
+ IContentService contentService,
+ IUmbracoDatabaseFactory umbracoDatabaseFactory,
+ IPublishedContentValueSetBuilder contentValueSetBuilder,
+ IOptionsMonitor indexingSettings)
+ : base(logger, true, null, contentService, umbracoDatabaseFactory, contentValueSetBuilder, indexingSettings)
+ {
+ }
}
diff --git a/src/Umbraco.Infrastructure/Services/IndexingRebuilderService.cs b/src/Umbraco.Infrastructure/Services/IndexingRebuilderService.cs
index 1263f52e5e..aaab2497ff 100644
--- a/src/Umbraco.Infrastructure/Services/IndexingRebuilderService.cs
+++ b/src/Umbraco.Infrastructure/Services/IndexingRebuilderService.cs
@@ -42,12 +42,6 @@ public class IndexingRebuilderService : IIndexingRebuilderService
///
public async Task 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 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
///
public Task 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);
- }
}
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs
index 1d7cf2e841..0b1f602907 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs
@@ -39,6 +39,7 @@ public class IndexInitializer
private readonly IContentTypeService _contentTypeService;
private readonly IDocumentUrlService _documentUrlService;
private readonly ILanguageService _languageService;
+ private readonly IOptionsMonitor _indexSettings;
public IndexInitializer(
IShortStringHelper shortStringHelper,
@@ -50,7 +51,8 @@ public class IndexInitializer
ILocalizationService localizationService,
IContentTypeService contentTypeService,
IDocumentUrlService documentUrlService,
- ILanguageService languageService)
+ ILanguageService languageService,
+ IOptionsMonitor 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());
- var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder);
+ var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder, _indexSettings);
return mediaIndexDataSource;
}