Skip to content

Conversation

@AndyButland
Copy link
Contributor

@AndyButland AndyButland commented Oct 1, 2025

Description

There are a number of places where we retrieve all languages from the database, when we only need all ISO codes.

This PR introduces a new method that will only retrieve that field from the database, and uses it wherever we currently get all languages just to select only the ISO code field.

So a small optimization to reduce the amount of data we pull from the database.

Copilot AI review requested due to automatic review settings October 1, 2025 08:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a performance optimization by adding a new method GetAllIsoCodesAsync() that retrieves only ISO culture codes from the database instead of full language objects when that's all that's needed.

  • Adds GetAllIsoCodesAsync() method to the language service and repository
  • Updates multiple locations that were fetching full language objects just to extract ISO codes
  • Includes comprehensive test coverage for the new functionality

Reviewed Changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Umbraco.Core/Services/ILanguageService.cs Adds interface definition for GetAllIsoCodesAsync() with default implementation and documentation improvements
src/Umbraco.Core/Services/LanguageService.cs Implements GetAllIsoCodesAsync() method that delegates to repository
src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs Adds GetAllIsoCodes() method interface with default implementation
src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs Implements optimized database query to fetch only ISO codes
tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/LanguageServiceTests.cs Adds integration test for new GetAllIsoCodesAsync() method
src/Umbraco.Core/Services/ContentValidationServiceBase.cs Updates to use new optimized method
src/Umbraco.Core/Services/ContentPublishingService.cs Updates two locations to use new optimized method
src/Umbraco.Core/Services/ContentEditingService.cs Updates to use new optimized method
src/Umbraco.Core/Routing/UrlProviderExtensions.cs Updates to use new optimized method
src/Umbraco.Core/Routing/PublishedUrlInfoProvider.cs Updates to use new optimized method
src/Umbraco.Cms.Api.Management/Factories/UserGroupPresentationFactory.cs Refactors to use existing GetIsoCodesByIdsAsync() method instead of fetching all languages
src/Umbraco.Cms.Api.Management/Factories/DictionaryPresentationFactory.cs Updates to use new optimized method
src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs Updates to use new optimized method
tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/ExamineExternalIndexSearcherTest.cs Updates to use new optimized method

@kjac
Copy link
Contributor

kjac commented Oct 1, 2025

@AndyButland I like the syntax change throughout the code changes, where (await _languageService.GetAllAsync()).Select(language => language.IsoCode) becomes await _languageService.GetAllIsoCodesAsync().

However, well intended as this is, it actually incurs a performance penalty if I'm not entirely mistaken.

LanguageService.GetAllAsync() calls LanguageRepository.GetMany(), which is an implementation on EntityRepositoryBase that utilizes the repository cache policy. The language repo provides a FullDataSetRepositoryCachePolicy, so all LanguageDto entities is likely cached by the time anyone attempts to read out all languages from the language service.

The new GetAllIsoCodesAsync() in LanguageService goes straight to the DB to fetch ISO codes.

Like I said, the syntax change is nice. Would it make sense to retain the default implementation of GetAllIsoCodesAsync() in ILanguageService, and remove the implementation in LanguageService? The default implementation uses GetMany(), so it won't hit the DB unless the cache is cleared.

Another alternative would be to implement GetAllIsoCodesAsync() as an extension method for ILanguageService. This might make it clearer what's going on caching wise.

@kjac kjac self-requested a review October 1, 2025 12:19
…/github.com/umbraco/Umbraco-CMS into v16/improvement/optimize-content-validation

# Conflicts:
#	src/Umbraco.Core/Services/ILanguageService.cs
@AndyButland AndyButland changed the title Performance: Retrieve only ISO codes from the database rather than full language objects if that's all we need Refactoring: Add extension method for retrieval of language ISO codes if that's all we need Oct 1, 2025
@AndyButland
Copy link
Contributor Author

Ah yes, that's a good point @kjac - thanks for catching that and apologies for the oversight. I've followed your extension method suggestion. So no performance improvement now, but likely worth having the syntax improvement as you suggest.

@kjac kjac enabled auto-merge (squash) October 1, 2025 17:47
Copy link
Contributor

@kjac kjac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 💪

@kjac kjac merged commit 78f4caa into main Oct 1, 2025
25 checks passed
@kjac kjac deleted the v16/improvement/optimize-content-validation branch October 1, 2025 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants