Conversation
Adds a new remote functions cache API. Simple example:
```ts
/// file: src/routes/data.remote.js
import { query, command } from '$app/server';
export const getFastData = query(async () => {
const { cache } = getRequestEvent();
cache('100s');
return { data: '...' };
});
export const updateData = command(async () => {
// invalidates getFastData;
// the next time someone requests it, it will be called again
getFastData().invalidate();
});
```
For more info see the updated docs.
This is very WIP, and the adapter part isn't implemented yet (there are a few ways to approach it and we need to agree on the other APIs first). But it workds in dev and preview (public cache is implemented as runtime cache which very likely needs some more hardening).
TODOs/open questions:
- right now `event.cache()` is "last one wins" except for tags which are merged. It probably makes sense to allow one entry for public cache and one for private, and either do "last one wins" or "lowest value wins"
- is `ttl` and `stale` descriptive enough? Should it be `maxAge` and `swr` instead (closer to the web cache nomenclature)?
- how to best integrate this with adapters? either they provide a file with some exports which are like hooks which we call at specific points (`setHeaders`, `invalidate` etc) or we don't do anything and do this purely via headers, and adapters can check these headers and either do runtime cache based on it and/or add cdn cache headers (though maybe they have to clone the response then; not sure how much of an overhead that is and if that matters)
- this only works for remote functions right now, and it only works when you are calling them from the client. We could additionally have a SvelteKit-native runtime cache for public caching, and/or the adapter can hook into this to cache somewhere else than in memory (Vercel can use runtime cache, CF can use their cache, etc; i.e. this is related to the question above). This way we get more cache hits between client/server calls (or rather, we can get full page request cache this way, which we don't have at all right now).
- can this be enhanced in a way that this is usable for full page requests, too (e.g. inside handle hook?). Private cache doesn't make sense there at least. I'd say it's possible to implement and would be intuitive with this API (we can say "do this in handle or load", or "assuming you use remote functions only we take the lowest cache across all of them as the page cache", etc etc, many possibilities) but we should do that later and not bother with it now.
🦋 Changeset detectedLatest commit: 7557320 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| // shareable across users (CDN caching) or private to user (browser caching); default private | ||
| scope: 'private', | ||
| // used for invalidation, when not given is the URL | ||
| tags: ['my-data'], |
There was a problem hiding this comment.
I don't think the URL is the right cache key here... it should probably be the remote function key instead. Also, tags should be additive, not replace the default key.
|
One thing I don't think is quite right here: Caching remote functions requires two coordinated layers of caching. One of them is a runtime cache at the server level, which needs to be used to cache direct-from-server remote function calls. This cache should be granular -- i.e. if I call Overall, I really think SvelteKit core should not do anything with the information from the cache API -- instead, the adapters should do everything:
|
| * Options for [`event.cache`](https://svelte.dev/docs/kit/@sveltejs-kit#RequestEvent) | ||
| */ | ||
| export interface CacheOptions { | ||
| ttl: string | number; |
There was a problem hiding this comment.
Should be a type like
`${number}d` | `${number}h` | `${number}m` | `${number}s` | `${number}ms`There was a problem hiding this comment.
Ms/day don't really make sense imo but otherwise yes; on my list of todos once we agree on the API 👍
|
Would |
Adds a new remote functions cache API. Simple example:
For more info see the updated docs.
This is very WIP, and the adapter part isn't implemented yet (there are a few ways to approach it and we need to agree on the other APIs first). But it workds in dev and preview (public cache is implemented as runtime cache which very likely needs some more hardening).
TODOs/open questions:
event.cache()is "last one wins" except for tags which are merged. After sitting with it for a while this is I think the most straightforward and understandeable solution, but we can also approach it differently.ttlandstaledescriptive enough? Should it bemaxAgeandswrinstead (closer to the web cache nomenclature)?setHeaders,invalidateetc) or we don't do anything and do this purely via headers, and adapters can check these headers and either do runtime cache based on it and/or add cdn cache headers (though maybe they have to clone the response then; not sure how much of an overhead that is and if that matters)