#how to manually invalidate everything in cache in a server function.

110 messages · Page 1 of 1 (latest)

hoary tinsel
#

I want to send a redirect and invalidate everything

vital wren
#

Are you not able to make the server function an action?

hoary tinsel
#

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

vital wren
#

what do your cache and action functions look like?

hoary tinsel
#
#

My assumption is that getUser would be defined always because of the routeguard, so I think getBoards cache is the issue

vital wren
#

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?

hoary tinsel
#

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

vital wren
#

i think i'd model your guards a bit differently

hoary tinsel
#

sure can you recommend something

vital wren
#

stepping back a bit, this redirect won't actually do anything, as redirect is ignored inside load functions

#

you need to depend on load in a createAsync for it to actually have effect

hoary tinsel
#

the redirect works

#
const load = cache(async () => {
    const user = await getUser();
    if (!user) {
        return redirect('/test');
    }
}, '(protected) load');
#

this redirects to test

vital wren
#

ah nvm i think it got changed so that works

#

i think the next thing i'd do is remove the protected guard entirely

hoary tinsel
#

can I ask the reasoning and the alternative?

vital wren
#

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 data

hoary tinsel
#

I'll try that, seems weird coming from prev paradigms though

#

usually auth is middleware afaik

vital wren
#

exactly, ensureAuthenticated is basically a middleware in this scenario

hoary tinsel
#

so basically instead of if (!user) return Error() you want me to if (!user) return redirect() ?

#

correct?

vital wren
#

pretty much

hoary tinsel
#

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

vital wren
#

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 not

hoary tinsel
#

I 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

vital wren
#

breaks in what way?

hoary tinsel
#

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

vital wren
#

it might be because you're not depending on it anywhere yet

hoary tinsel
#

do layout loads don't consider as depending?

vital wren
#

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 top

hoary tinsel
#

got it, coming from svelte I thought they do have deps

vital wren
#

createAsync and the like do, they're the reactive part

#

preload is just to help you start fetching data as early as possible

hoary tinsel
#

what is the diff b/w preload and load?

vital wren
#

load is the deprecated name, they're the same thing

#

preload more accurately conveys that it's an optimization, rather than a dedicated route loader

hoary tinsel
#

can a route component be async btw?

vital wren
#

no

hoary tinsel
#

thank you so much, I think I will refactor the code and see if that helps

vital wren
#

for (auth) i'd do something like this

import { cache, redirect } from '@solidjs/router';
import { JSXElement } from 'solid-js';
import { getUser } from '~/db/utils/users';

export const route = { load: () => getUser() };

export default function (props: { children: JSXElement }) {
    const user = createAsync(() => getUser());
    const navigate = useNavigate();

    createEffect(() => {
      if (user()) navigate("/");
    })

    return <>{props.children}</>;
}
hoary tinsel
#

redirect doesn't work on client?

vital wren
#

redirect only works in cache/action functions

hoary tinsel
#

got it, thanks again 🙂

vital wren
#

i'm not 100% sure if it'll work but i think it's a better design to go off of

hoary tinsel
#

I'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?

vital wren
#

what do you mean by 'works'? createEffect usually just runs later than createRenderEffect

#

since it won't run until any suspense boundaries above it resolve

hoary tinsel
#

for 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

vital wren
hoary tinsel
#

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

vital wren
#

You’re reading cookies from getRequestEvent right?

hoary tinsel
#

yes and passing the nativeevent to getCookies

vital wren
#

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

hoary tinsel
#

do nativeEvent also has that quality?

vital wren
#

Yeah

#

You don’t even have to pass the event to getCookies

#

It can pull it from the request lifecycle on its own

hoary tinsel
#
    const event = getRequestEvent()!;
    const user = event.locals.user;

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

vital wren
#

If you’re setting to locals in middleware then yeah it should be present in both components and server functions

hoary tinsel
#

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 great

vital wren
#

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

hoary tinsel
#

let me send some logs

#

DEBUGPRINT[2]: middleware.ts:9: token= undefined
DEBUGPRINT[1]: signin.tsx:16 (after use server;)
DEBUGPRINT[1]: boards.ts:11: cookie= null

#

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?

vital wren
#

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 request

hoary tinsel
#

any fixes?

vital wren
#
  1. don't do auth in middleware 😅
hoary tinsel
#

the createEffect stuff didn't work too but I'll go back to that commit and get some debug logs as well

vital wren
#

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 fetches

hoary tinsel
#

yup, maybe setCookie invocatoin can set a flag or something

vital wren
#

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 client

hoary tinsel
#

thanks for the info, appreciate it 🙂