how to manually invalidate everything in cache in a server function.
I want to send a redirect and invalidate everything
61 Replies
Are you not able to make the server function an action?
It is already an action, but it doesn't seem to invalidate the functions, I can confirm the code works if I remove the cache wrapper from the relevant functions
what do your cache and action functions look like?
Sign in action
https://github.com/vanillacode314/kanban/blob/main/src/routes/(auth)/signin.tsx#L14
Relevant route_guard
https://github.com/vanillacode314/kanban/blob/main/src/routes/(auth).tsx#L5
The component where the issues is happening, (serverBoards returns Error)
https://github.com/vanillacode314/kanban/blob/main/src/routes/(protected)/index.tsx#L14
The get-boards function, if I remove cache from here, it works
https://github.com/vanillacode314/kanban/blob/main/src/db/utils/boards.ts#L7
My assumption is that getUser would be defined always because of the routeguard, so I think getBoards cache is the issue
ohh you want the cache function to trigger the revalidation
i assume because you want the guard to rerun if an auth error is thrown?
no the auth guard works correct, but once it redirects to / after signin, the auth guard has user != null but in getBoards() there is still Error('Unauthorized')
which I think is because of cache
since If I refresh the page it works
also getBoards() doesn't run on the client again
all of this works if I turn off js, but I think that is because it refreshes on form post
i think i'd model your guards a bit differently
sure can you recommend something
stepping back a bit, this
redirect
won't actually do anything, as redirect
is ignored inside load
functionsyou need to depend on
load
in a createAsync
for it to actually have effectthe redirect works
this redirects to test
ah nvm i think it got changed so that works
i think the next thing i'd do is remove the
protected
guard entirelycan I ask the reasoning and the alternative?
yeah i'll get into it
instead, i'd have an
ensureAuthenticated
function which getBoards
, createBoard
, etc can call, which would call getUser
and throw the /signin
redirect itself
that way you're not relying on a separate guard to do the redirect, it's just baked in to your dataI'll try that, seems weird coming from prev paradigms though
usually auth is middleware afaik
exactly,
ensureAuthenticated
is basically a middleware in this scenarioso basically instead of
if (!user) return Error()
you want me to if (!user) return redirect()
?
correct?pretty much
Thanks, I'll try that
appreciate the help
it still has the same issue, now instead of erroring it redirects back to the signin page until refresh
yeah imma get there
next thing i'd do would be wrap
getUser
in cache
that then becomes your source of truth for the frontend for if a user exists or notI am not sure if you remember me from the other thread yesterday, if I add cache to getUser then it breaks the app till refresh everywhere. Can confirm that is still happening
breaks in what way?
for example if I sign in, it won't redirect till refresh, same with signout etc..., basically getUser won't update till I refresh
it sticks to the cache value
the action doesn't invalidate it I think
it might be because you're not depending on it anywhere yet
do layout loads don't consider as depending?
nah
load
/preload
is just considered a one off thing
realistically your whole app should work without load
/preload
they're just an optimisation to apply on topgot it, coming from svelte I thought they do have deps
createAsync
and the like do, they're the reactive part
preload
is just to help you start fetching data as early as possiblewhat is the diff b/w preload and load?
load
is the deprecated name, they're the same thing
preload
more accurately conveys that it's an optimization, rather than a dedicated route loadercan a route component be async btw?
no
thank you so much, I think I will refactor the code and see if that helps
for
(auth)
i'd do something like this
redirect doesn't work on client?
redirect
only works in cache/action functionsgot it, thanks again 🙂
the idea with this is that it depends on
getUser
, rather than another cache function, so if it's invalidated it should hopefully refetch if necessary
i'm not 100% sure if it'll work but i think it's a better design to go off ofI'll report back if it works or nto
createRenderEffect works here and not createEffect. I assume that is because effect runs after children are run?
what do you mean by 'works'?
createEffect
usually just runs later than createRenderEffect
since it won't run until any suspense boundaries above it resolvefor anyone struggling in the future with the same issue, the createEffect stuff also didn't work, in the end I just wrote a middleware and attached the user to event.locals.user and that worked
also I had to remove cache from getUser
Did the effect just not run or something?
actually the issue is something else, see this post: https://discord.com/channels/722131463138705510/1271832167588036650
even the middleware didn't work, it was a fluke
the main issue is forwarding headers from client I think
I would create a fetch wrapper but obv. I cannot control how server functions are called
You’re reading cookies from getRequestEvent right?
yes and passing the nativeevent to getCookies
Server functions are special in that you usually don’t have to pass through cookies
Since they can use the same request data as the ssr invocation
do nativeEvent also has that quality?
Yeah
You don’t even have to pass the event to getCookies
It can pull it from the request lifecycle on its own
if this is in a server function, even if it's called on ssr in server, it should have the locals set from middleware?
it doesn't have the headers as you mention
If you’re setting to locals in middleware then yeah it should be present in both components and server functions
let's say if I have a action signin, it calls
setCookie
and redirects, now I assume this would trigger ssr and call server functions in server, would the server function get the cookie then?
the main issue happens to me on signin and signout
otherwise everything works greatThis won’t ssr, it’ll client navigate and call the server functions
The cookie should be included tho
The cookie not being present might be related to something else though
As that action will be a single flight mutation which will call getUser after completing the action, and the cookie might only be set on the response at that point in time, not the request
let me send some logs
this is the chain of events on login
this is the server logs to be clear
the middleware isn't call after signin
shouldn't it be called before boards.ts as it's a severfunction?
Ok yeah i think
signIn
is a single flight mutation here
What Start is doing is performing the signIn
action, and then because it knows that the route you're redirecting to needs getBoards
it's fetching that before returning the action response
So it's doing the action and data fetch in the same requestany fixes?
1. don't do auth in middleware 😅
the createEffect stuff didn't work too but I'll go back to that commit and get some debug logs as well
but the cookie not being present in
getBoards
seems to be a limitation of the single flight mutations implementation at the moment
It might be necessary for response headers from the action to be set on the request before executing single flight data fetchesyup, maybe setCookie invocatoin can set a flag or something
You can also set
singleFlight={false}
on <Router>
to disable SFM for now
So the data fetch would be done in a second request by the clientthanks for the info, appreciate it 🙂
That worked, thanks, this was baffling me for 2 days straight