Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Umbraco.Core/Configuration/Models/IndexingSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
47 changes: 41 additions & 6 deletions src/Umbraco.Infrastructure/Examine/ContentIndexPopulator.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -20,20 +24,45 @@
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>
public ContentIndexPopulator(
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>>())

Check warning on line 65 in src/Umbraco.Infrastructure/Examine/ContentIndexPopulator.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/dev)

❌ New issue: Code Duplication

The module contains 2 functions with similar structure: ContentIndexPopulator,ContentIndexPopulator. Avoid duplicated, aka copy-pasted, code inside the module. More duplication lowers the code health.
{
}

Expand All @@ -46,14 +75,21 @@
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));
_contentValueSetBuilder = contentValueSetBuilder ?? throw new ArgumentNullException(nameof(contentValueSetBuilder));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_publishedValuesOnly = publishedValuesOnly;
_parentId = parentId;
_indexingSettings = indexingSettings.CurrentValue;

indexingSettings.OnChange(change =>
{
_indexingSettings = change;
});
}

private IQuery<IContent> PublishedQuery => _publishedQuery ??=
Expand All @@ -75,7 +111,6 @@
return;
}

const int pageSize = 10000;
var pageIndex = 0;

var contentParentId = -1;
Expand All @@ -86,11 +121,11 @@

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);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)
{
Expand Down
35 changes: 29 additions & 6 deletions src/Umbraco.Infrastructure/Examine/MediaIndexPopulator.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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)
Expand All @@ -46,7 +70,6 @@ protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)
return;
}

const int pageSize = 10000;
var pageIndex = 0;

var mediaParentId = -1;
Expand All @@ -60,7 +83,7 @@ protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)

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)
Expand All @@ -70,6 +93,6 @@ protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes)

pageIndex++;
}
while (media.Length == pageSize);
while (media.Length == _indexingSettings.BatchSize);
}
}
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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,
Expand All @@ -23,4 +26,14 @@ public PublishedContentIndexPopulator(
: 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)
{
}
}
23 changes: 0 additions & 23 deletions src/Umbraco.Infrastructure/Services/IndexingRebuilderService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Examine;

Check warning on line 1 in src/Umbraco.Infrastructure/Services/IndexingRebuilderService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/dev)

❌ New issue: String Heavy Function Arguments

In this module, 41.7% of all arguments to its 7 functions are strings. The threshold for string arguments is 39.0%. The functions in this file have a high ratio of strings as arguments. Avoid adding more.
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
Expand Down Expand Up @@ -42,21 +42,13 @@
/// <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);
return attempt.Success;
}
catch (Exception exception)
{
// Ensure it's not listening
index.IndexOperationComplete -= Indexer_IndexOperationComplete;
_logger.LogError(exception, "An error occurred rebuilding index");
return false;
}
Expand All @@ -70,19 +62,4 @@
/// <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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -50,7 +51,8 @@ public IndexInitializer(
ILocalizationService localizationService,
IContentTypeService contentTypeService,
IDocumentUrlService documentUrlService,
ILanguageService languageService)
ILanguageService languageService,
IOptionsMonitor<IndexingSettings> indexSettings)
{
_shortStringHelper = shortStringHelper;
_propertyEditors = propertyEditors;
Expand All @@ -62,6 +64,7 @@ public IndexInitializer(
_contentTypeService = contentTypeService;
_documentUrlService = documentUrlService;
_languageService = languageService;
_indexSettings = indexSettings;
}

public ContentValueSetBuilder GetContentValueSetBuilder(bool publishedValuesOnly)
Expand Down Expand Up @@ -91,7 +94,8 @@ public ContentIndexPopulator GetContentIndexRebuilder(IContentService contentSer
null,
contentService,
umbracoDatabaseFactory,
contentValueSetBuilder);
contentValueSetBuilder,
_indexSettings);
return contentIndexDataSource;
}

Expand All @@ -105,7 +109,7 @@ public MediaIndexPopulator GetMediaIndexRebuilder(IMediaService mediaService)
_shortStringHelper,
_contentSettings,
StaticServiceProvider.Instance.GetRequiredService<IContentTypeService>());
var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder);
var mediaIndexDataSource = new MediaIndexPopulator(null, mediaService, mediaValueSetBuilder, _indexSettings);
return mediaIndexDataSource;
}

Expand Down