Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API methods for cache storage #7

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

BlazerYoo
Copy link

No description provided.

@getify
Copy link
Member

getify commented Jan 7, 2025

this is really interesting, thank you!

I am curious about the choice to store all the data in a single cache entry, instead of a single cache entry per "key" in the store. What are your thoughts on the tradeoffs here?

@BlazerYoo
Copy link
Author

Thank you!

I think that storing all the data in a single cache entry may allow for lower overhead since metadata is stored per cache entry.

On the other hand having a single cache entry store one key-value pair may support more concurrency with Independent updates being safer and easier to manage?

I primarily wanted to isolate all of data manually added to cache from any caching done by the websites by creating a separate "generic-key-value-cache" to store all the manual data.

@getify
Copy link
Member

getify commented Jan 8, 2025

Yeah, I see that reasoning, and agree with the observations.

For comparison:

  • local-storage and session-storage adapters store individual key-val pairs (since the storage medium is already key-val).
  • cookie stores each key-val pair in separate cookies
  • OPFS and OPFSWorker store each key-val pair in separate "files" in the virtual filesystem -- SIDE NOTE: this may not be "safe" if the key name isn't a suitable name for a file, but I'm not aware of what restrictions if any there are for those, so left the topic alone for now.
  • idb uses the idb-keyval library, which technically makes a single big "JSON" object in the indexed-db store, but... the adapter uses that abstraction as a key-val store, like local-storage and session-storage.

So, in summary, all the existing adapters basically store entries separately (with the slight technical exception of idb).

This would make cache different from the rest. But I'm not convinced that it's a bad difference we should avoid. Still trying to decide, and open to input.

But to state other tradeoffs explicitly:

  1. obvious performance downside: all read/write operations require handling the ENTIRE store all at once, which when small is no big deal, but if large, might be.

  2. a single large cache entry might be (not sure on this!?) more subject to cache eviction by the browser. I am wondering whether this is true or not.

    Do you know how the "expiration" (and eviction) of artificially created cache entries is handled by the browser? Is an artificial cache entry permanent, or does it have a maximum lifetime (like cookies do, of 400 days)?

One option might be to store each key-val pair as separate cache entries, but to have a naming prefix that sort of keeps all of them sorted together... like cache-kvstore-{{KEY}} for example. If we did that, we'd need to explore (same as the concern on the OPFS) if there are any restrictions on the names of "files" in the cache.

@BlazerYoo
Copy link
Author

Yeah I agree.

I just updated adapter.cache.js so that each key-value pair is stored in separate cache entries.

I had the cache entries be prefixed with cache-kvstore- (as per your suggestion).

On your point about expiration/eviction of manually created cache entries, there doesn't seem to be a default expiration unless manually set in the header (i.e. max-age: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control).

I'm not sure if storing key-value pairs in separate cache entries would make it any more or less subject to eviction. But per https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria#how_is_data_evicted, "When an origin's data is evicted by the browser, all of its data, not parts of it, is deleted at the same time. If the origin had stored data by using IndexedDB and the Cache API for example, then both types of data are deleted."

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.

2 participants