Next.js Discord

Discord Forum

Making use of 3rd party client library that uses `fetch` internally

Unanswered
Asian paper wasp posted this in #help-forum
Open in Discord
Asian paper waspOP
It's @planetscale/database to be exact. It uses fetch internally and uses POST requests to communicate with DB, including SELECT statement. So Next.js' data caching behavior applies here.

The problem is that this is also true within server actions, where DML operations are cached in the Data Cache layer and only fired once when being called in an SSG page, and because it's a 3rd party client library, I can't seem to have access to the cache option at the query level, while I do be able to override the fetch config at a global level.

Is there a way to instruct Next.js NOT to cache DML operations, including making use of unstable APIs?

23 Replies

iirc @planetscale/database has a way that you can pass your own fetch function... you could just make your own that wraps nextjs fetch with cache disabled
Asian paper waspOP
Yeah, I noticed that, but that's only at the global level. I've also thought of dynamically setting the cache value by inspecting the request body, which I'm yet to find a pattern of how to differentiate between DML and R/O operations
but personally i have tried the prisma planetscale new thing with no config, and no caching has occured for me (dynamic page but no other config) - tested on prod vercel
Asian paper waspOP
Yeah, because they hard coded no-store, which obviously doesn't work in static pages
ahh ok... then whats the issue?
Asian paper waspOP
I've tried to unset that, but that turns out causing server actions to cache what it's not supposed to cache
lol i was just going to use unstable_cache with prisma and be done with caching...
Asian paper waspOP
Basically, a DML in @planetscale/database is just a sequence of POST requests. By unsetting cache, and being unable to manually set cache for a specific query, apparently, Next.js thought it was a good idea to cache that as well.
im struggling to see what your intended outcome is... like how do you want nextjs to be caching?
could you just fork the library and do all your fixes there?
Asian paper waspOP
OK, let me break this down. There are two operations done:

1. SELECT from a table - called in RSC
2. UPSERT the same table - called in server actions

How planetscale does is both are done via POST requests that is called via fetch. Now the problem is, Next.js by default thought both operations were catchable, even though the 2nd operation shouldn't.
I can go and specify no-store, but that can only applied at the global level, which makes the 1st operation unable to be called in static pages
I can also attempt to set no-store dynamically by inspecting the args of fetch being called (kind of like interceptor/middleware), but
1. that's hacky
2. I've yet to find a way to separate DML and R/O operations this way.
wait so, how should nextjs know that it should catch it (also what does catch mean here... cache the result)...
as you say that it is a post req for both.. so is there something that makes it obvious that it should be cached/not...
Asian paper waspOP
I'm trying to see whether there are something I can do so in the request body. So far no luck though
Also, off-topic, I am not even sure whether unstable_cache will help in this case since It uses fetch internally. I have no idea how Next.js will react when it sees both unstable_cache and no-store at the same time.
That's why all those fancy caching stuff should have been implemented using stuff like unstable_cache in all cases from the very beginning, instead of monkey patching a native API, which obviously will introduce a bunch of issues
Tbh I don't know much about this caching business... I just assumed that unstable cache just cared about the returned data
Asian paper waspOP
Alternatively, I guess I can try calling cookies() in the server actions to mislead Next.js not to cache the server action
Though that's hacky AF
Asian paper waspOP
Yep, that "works". Just do
export const upsertStuff = () => {
  cookies(); // mislead Next.js not to cache the following fetch response
  db.upsertViaFetch();
}
That's cool and sad at the same time...
Asian paper waspOP
It seems that way. At least that appears to be the least hacky way with minimal overhead.