Skip to content

Conversation

@callumbwhyte
Copy link
Contributor

As discussed on #15533 a small performance issue can exist at scale whereby each subsequent call to Umbraco.GetDictionaryValue("...") for non-existent keys results in a database lookup.

This PR implements an option to cache null values in the repository layer, and enables for the DictionaryByKeyRepository repository, following @Migaroez's stellar recommended implementation here.

@github-actions
Copy link

github-actions bot commented Jan 15, 2024

Hi there @callumbwhyte, thank you for this contribution! 👍

While we wait for one of the Core Collaborators team to have a look at your work, we wanted to let you know about that we have a checklist for some of the things we will consider during review:

  • It's clear what problem this is solving, there's a connected issue or a description of what the changes do and how to test them
  • The automated tests all pass (see "Checks" tab on this PR)
  • The level of security for this contribution is the same or improved
  • The level of performance for this contribution is the same or improved
  • Avoids creating breaking changes; note that behavioral changes might also be perceived as breaking
  • If this is a new feature, Umbraco HQ provided guidance on the implementation beforehand
  • 💡 The contribution looks original and the contributor is presumably allowed to share it

Don't worry if you got something wrong. We like to think of a pull request as the start of a conversation, we're happy to provide guidance on improving your contribution.

If you realize that you might want to make some changes then you can do that by adding new commits to the branch you created for this work and pushing new commits. They should then automatically show up as updates to this pull request.

Thanks, from your friendly Umbraco GitHub bot 🤖 🙂

@emmagarland
Copy link
Contributor

Hi @callumbwhyte!

Thanks for your PR to fix #15533, where there is a performance hit if null values need to be looked up in the DB.

One of the Core Collaborators team will review this as soon as possible - and from the issue it seems like one that we'll want HQ to have a glance over too, so we'll contact them about it! (cc @Migaroez)

Best wishes

Emma

@Migaroez
Copy link
Contributor

Code wise this look what we proposed 👍

@mikecp mikecp self-assigned this Feb 7, 2024
mikecp
mikecp previously requested changes Feb 7, 2024
@mikecp
Copy link
Contributor

mikecp commented Feb 7, 2024

Hi @callumbwhyte ,

Thanks for your PR!
I have tested your changes and got some difficulties in getting a "no database access" situation, so I have left some comments on the files. It would be super great if you could have a look at them and let me know what you think 😁
(cc @Migaroez😉)

Cheers!

@madsoulswe
Copy link
Contributor

Any updates/progress on this 😄 this would be super nice to have!

@madsoulswe
Copy link
Contributor

Any chans this is going to make the 13.6 release 😅 @Migaroez

@AndyButland AndyButland changed the base branch from contrib to v13/dev January 28, 2025 11:20
@AndyButland
Copy link
Contributor

I've made some updates to this to resolve the issues raised by @mikecp above. Think I have the logic right now. It wasn't quite as simple as first thought, as I realised if we cache a literally null value, we then can't tell from the cache retrieval if we have found a cached value or not... the value will be null in the case of an existing value that's not yet cached, or a cached null value.

So I've got around this by caching a string to represent null, and then built the logic around that.

It needs a further review of my amends, so if @mikecp, @Migaroez or @callumbwhyte would like to, please do, and hopefully we can get this into 13+.

To test I've added the following to a view and created one dictionary item and not the other:

<div>Value of "Exists": @Umbraco.GetDictionaryValue("Exists")</div>
<div>Value of "DoesNotExist": @Umbraco.GetDictionaryValue("DoesNotExist")</div>

I've confirmed I see the expected value on the front-end. And I've added a debugger to the DefaultCacheRepository.Get() method to step through and verify that we return cached values/make calls to the database as we would expect.

Finally I've populated the DoesNotExist key and verified the cache is invalidated so we see the expected value on the front-end.

@AndyButland AndyButland requested a review from mikecp January 28, 2025 13:11
@callumbwhyte
Copy link
Contributor Author

@AndyButland Changes look good to me!

Thanks for picking this up - I've been meaning to come back to this for some time, but time seems to be the exact issue for me lately...!

@Migaroez Migaroez requested a review from AndyButland February 3, 2025 16:18
This reverts commit 8befb43 "Improve generic NullValueCachePolicyResolver"
Also reverts 8adf0a2 - Made the NullValueRepresentation overwritable in a generic manner
And 8adf0a2 - Made the NullValueRepresentation overwritable in a generic manner
@Migaroez Migaroez requested a review from AndyButland February 4, 2025 09:52
Copy link
Contributor

@AndyButland AndyButland left a comment

Choose a reason for hiding this comment

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

Review and testing steps described in #15576 (comment)

@AndyButland AndyButland enabled auto-merge (squash) February 4, 2025 10:38
@AndyButland AndyButland dismissed mikecp’s stale review February 4, 2025 11:29

Requested amends have been handled.

@AndyButland AndyButland merged commit 6620aca into umbraco:v13/dev Feb 4, 2025
19 checks passed
@umbracocommunity
Copy link

This pull request has been mentioned on Umbraco community forum. There might be relevant details there:

https://forum.umbraco.com/t/usync-imported-translations-get-flat-structure-instead-of-being-nested/1754/3

@KevinJump
Copy link
Contributor

Hi,

Just a heads up, this appears to effect subsequent lookups of dictionary items by their key (the string key, not the guid id). that have been just created, e.g

if an item has just been created then looking for it by this key returns null.

// code to create some dictionary (item) here...
_localizationService.Save(item);

// later in sequence.... 

// lookup
_localizationService.GetDictionaryItemByKey(keyString);

I am not sure how this works on v13.6.0 but not v13.7.0 - and this does look like the only change around that.

@umbracocommunity
Copy link

This pull request has been mentioned on Umbraco community forum. There might be relevant details there:

https://forum.umbraco.com/t/dictionary-cache-regression/6041/4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants