"use cache" arguments and tags
Unanswered
Chow Chow posted this in #help-forum
Chow ChowOP
I'm looking at the new "use cache" directive and considering giving it a try. I am using
How exactly does the capture work? If I use
unstable_cache
for a while now in existing projects and I was generally pretty happy with it. This new approach definitely looks better but I have on pretty important question about the argument capture for creating the cache entries.Any serializable arguments (or props) passed to the cached function, as well as any serializable values it reads from the parent scope, will be converted to a format like JSON and automatically become a part of the cache key.
How exactly does the capture work? If I use
cacheTag
for the cached function, will it affect the capture in any way or are the tags purely for revalidation? I was using keyParts
argument of unstable_cache
to affect the caching behaviour but now I'm afraid that since it's "automatic" I won't be able to do that.5 Replies
Chow ChowOP
https://github.com/Haaxor1689/talent-builder/blob/master/src/server/api/helpers.ts
Here are my helpers I was using with
Here are my helpers I was using with
unstable_cache
that I would ideally want to get rid of completely and achieve the same thing with just using "use cache"
with cacheTag
and cacheLife
Chow ChowOP
Ok so I rewrote it and what I feared happened, I'm getting errors that some values like callbacks and zod schema can't be serialized. Is there a way to manually specify what should the "dependencies" of the cache be so I can pass arbitrary callback to it? Here is the code:
Where
If there is some fundamental design issue with my solution I'm definitely open to suggestions.
export const serverQuery = <
SessionType,
Func extends ProcedureFn<Input, SessionType>,
Input extends z.ZodTypeAny = z.ZodUndefined
>({
input,
session,
queryKey,
query
}: QueryProps<SessionType, Func, Input>): ProcedureReturn<
SessionType,
Func,
Input
> &
RevalidateType<Input> => {
const handler = async (val: z.infer<Input>) => {
const s = session ? await session() : null;
return cache(async () => {
'use cache';
cacheTag(queryKey, `${queryKey}: ${JSON.stringify(val)}`);
cacheLife({
stale: 60 * 5,
revalidate: 60 * 60 * 24 * 30,
expire: INFINITE_CACHE
});
console.log('[MISS]:', queryKey);
return (await query(input?.parse(val), s as never)) ?? null;
})();
};
handler.revalidate = (val?: z.infer<Input>) => {
console.log('[CLEAR]:', queryKey, val ?? 'ALL');
return revalidateTag(
val ? `${queryKey}: ${JSON.stringify(val)}` : queryKey
);
};
return handler as never;
};
Where
input
is a zod schema and query
is the actual callback that "does the work". And here is example usage:export const getCrashReports = serverQuery({
queryKey: 'getCrashReports',
session: SessionType.admin,
query: async () =>
await db.query.crashReports.findMany({
orderBy: asc(crashReports.created),
limit: 50
})
});
If there is some fundamental design issue with my solution I'm definitely open to suggestions.
Chow ChowOP
hmm nope it just doesn't work, I keep getting this error
Error: Attempted to call a temporary Client Reference from the server but it is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.
what does it have to do with client? this cache should be fully server side right?
Chow ChowOP
any reply here would be really appreciated