Skip to content

feat(cache): add cache key helper auto-including provider name and options#239

Closed
sushichan044 wants to merge 7 commits intounjs:mainfrom
sushichan044:sushichan044-202509051803-font-cache-key
Closed

feat(cache): add cache key helper auto-including provider name and options#239
sushichan044 wants to merge 7 commits intounjs:mainfrom
sushichan044:sushichan044-202509051803-font-cache-key

Conversation

@sushichan044
Copy link
Contributor

@sushichan044 sushichan044 commented Sep 8, 2025

resolves #184

This PR introduces a unified cache key factory that automatically includes provider name and options in generated cache keys, ensuring cache invalidation when provider configuration changes.
All built-in providers have been updated to use the new cache key factory.

Problem

Previously, cache keys were not provider-aware, leading to stale cache reuse when:

  • Provider options changed (e.g., experimental.glyphs in Google provider)

Additional Information

I should be add documentation later to support implementing a custom provider,
including safe ways to cache key generation.

Copy link
Collaborator

@florian-lefebvre florian-lefebvre 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 overall! Just a comment on the API of cacheKey

sushichan044 and others added 2 commits September 25, 2025 11:38
Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
@sushichan044 sushichan044 changed the title implement cache key builder draft feat(cache): add cache key helper auto-including provider name and options Sep 26, 2025
@sushichan044 sushichan044 marked this pull request as ready for review October 24, 2025 02:11
@sushichan044
Copy link
Contributor Author

@florian-lefebvre
Sorry to bring this up after getting your approval, but I realized that with the current implementation, we can’t modify the interface of ctx.cacheKey().
So I’m thinking it might be better to accept a single Array<string | Record<string, any>> instead of using variadic arguments. What do you think?

@florian-lefebvre
Copy link
Collaborator

I realized that with the current implementation, we can’t modify the interface of ctx.cacheKey().

Why is that?

@sushichan044
Copy link
Contributor Author

I was thinking about the possibility that we wouldn’t be able to add any new options later.

That said, it’s unlikely that we’ll need to add options to this function, so I think it’s fine to ignore that concern.

@florian-lefebvre
Copy link
Collaborator

Ah gotcha. Also unifont is in pre v1 so breaking changes can occur at any time.

@danielroe I'd like your review on this when you have time

Comment on lines +52 to +55
const unifontContext: ProviderContext = {
storage,
cacheKey: createCacheKeyFactory(provider._name, provider._providerOptions),
}
Copy link
Member

Choose a reason for hiding this comment

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

could we do this automatically rather than exposing the cacheKey to the provider? ie. automatically setting the cacheKey as the first part of any key the provider accesses?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@danielroe I think we can do that by wrapping storage interface. I'll try it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@danielroe

There are two reasons why the cacheKey helper is exposed to the provider.
One, as you mentioned, is to automatically account for the provider name and options — this can be done automatically by changing the internal implementation.

The other is to allow users to safely generate keys simply by passing the data they want to use as the key source, without manually performing hashing or string concatenation.
To achieve this, I believe we would need to modify the interface of ProviderContext["storage"].
If we decide to proceed, it would likely require a separate PR.

e.g.

const fonts = await ctx.storage.getItem(
  ["data.json", fontFamily, defaults], // automatically hashed and concatinated
  () => getFontDetails(fontFamily, defaults),
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Anyway, I’d like to split out only reason 1 into a separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@danielroe @florian-lefebvre
I’ve created a draft implementation in #281 that automatically includes the provider name and options in the cache key.
Could you take a look when you have time?

@sushichan044
Copy link
Contributor Author

sushichan044 commented Nov 21, 2025

Closing this PR since the design was changed in #281.

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.

Cache does not take provider config into account

3 participants