-
-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GoTrueClient
Memory Leak
#856
Comments
I've been playing with something like this, but it won't work in React Native as there is no support for https://github.com/nbarrow-inspire-labs/bug-demo/blob/main/src/IntervalTimer.ts |
I just wanted to bump this and see if there's a potential work-around while ReactNative works on supporting |
A pub/sub method might be more desireable: The static class can act as a publisher, using This would solve the garbage collection issue, as the subscribers exist independently of the one main (static) publisher; if an instance is due for garbage collection, so too would its event subscriber, allowing instances to be garbage collected while the static class publisher is just always running in the background. Perhaps a library like https://docs.evt.land/ while supports (perportedly) all JS runtimes. |
Is there any updates on this? |
Is this only for React Native? |
As far as I can tell, it effects non-Deno and non-Node.js environments, because the solution attempted previously only fixes this leak for Deno and Node: |
For the time being, I think this will work (still testing): import {useEffect, useState} from "react";
import {createClient} from "@supabase/supabase-js";
import AsyncStorage from "@react-native-async-storage/async-storage";
export const useSupabaseClient = (supabase: {
url: string;
keys: {
anon: string;
}
}) => {
// this is important too, to use an initializer function in setState
const [client] = useState(() => createClient(supabase.url, supabase.keys.anon, {
auth: {
storage: AsyncStorage
}
}));
useEffect(() => {
return () => {
client.auth.stopAutoRefresh().then(); // this should dump the `Timeout`, eliminating all refs, and allow garbage collection
}
}, []);
return client;
}; The operative line is: client.auth.stopAutoRefresh().then(); // this should dump the `Timeout`, eliminating all refs, and allow garbage collection |
From what I can see, ^ seems to work until Hermes has support for |
Not sure why it's a "memory leak," probably the React Native runtime is a bit bad at tracking this. But, as far as I know, you don't have to use this in React Native. You can call Take a look at these docs: https://supabase.com/docs/reference/javascript/auth-startautorefresh |
@hf the only memory leak will occur in react runtimes that are not (a) Node.js and (b) Deno because of the way Basically, in non-Node.js and non-Deno runtimes (like If you see my example above (#856 (comment)), my temporary fix was already using the I also have a solution using the |
@nbarrow-inspire-labs i guess I'm a bit confused ...I'm also dealing with a memory leak but I use Supabase in a Node.JS context so it's still affecting me as well, not just in React Native (etc.). Calling .getUser() causes my memory in a Fastify server to steadily increase over time 🤔 |
@uncvrd can you try the const [client] = useState(() => createClient(supabase.url, supabase.keys.anon, {
auth: {
debug: true
}
})); Perhaps the logs will give some insight? Also, if you see the number of clients increasing (each log statement indicates which number client it is) then you might be having the exact same issue, but for a different reason. |
@uncvrd yeah you definitely have a memory leak problem (youre correct that |
For sure! I'll post snippets for now and if needed, can break out a test repo if needed I have a simple k6 load test hitting my endpoint. I use
Once this HTTP request makes it's way to my server, the requests are sent off in parallel to the respective endpoints, the network request first passes through a context function to define the properties I'll have access to within the business logic of the backend endpoint. This reduced context returns an object that has the user (set to null by default) and a function that uses
The endpoints that started with
As you can see, this calls the
I had previously used an old
Does this help a bit? I know it's a lot. I can make a video demo stepping through all of these hoops |
@uncvrd given your usecase, it sounds like the If so, I would modify all of your If you are not destroying the ctx after each request, you will still likely want to implement some way of cleaning-up every single supabase instance you make, by calling Note that garbage collection, in my tests, took upto 15-20 seconds, so it might take around that amount of time before you stop seeing logs. Try this and let me know if that decreases memory usage. |
I created a PR that would at least notify users if their platform will experience a memory leak: #867 |
@nbarrow-inspire-labs really appreciate your time and insight. I'm going to try the
Not quite sure why the above would help but just wanted to try setting the auth instead of having supabase try to parse the cookie for me to knock out that hypothesis. I'm attempting to disable a couple properties, first just the
But I would like to try https://supabase.com/docs/reference/javascript/auth-admin-getuserbyid |
@uncvrd yeah I would definitely call |
@nbarrow-inspire-labs so i set |
@uncvrd I havne't tried the |
@nbarrow-inspire-labs After inspecting the source code, I guess I don't understand how calling Line 2078 in 92fefbd
which is only set if Line 2224 in 92fefbd
With this disabled, I don't think this would fix things :/ My next guess was that the supabase client is being initialized with an inmemory storage adapter when Line 238 in 92fefbd
Where I thought that js object might be slowly getting filled with k/v pairs but when
ugh, I'll keep searching |
TLDR
This line is causing a memory leak:
https://github.com/supabase/gotrue-js/blob/15c7c8258b2d42d3378be4f7738c728a07523579/src/GoTrueClient.ts#L2040
setInterval
will persist even if the object calling it (in this case,GoTrueClient
) has been dereferenced. This prevents garbage collection (assetInterval
is still holding a reference, even if the user has lost all references) and leads to the memory leak.A solution seems to have been attempted, but it is not working in (at the very least) React Native, where I encountered this issue:
https://github.com/supabase/gotrue-js/blob/15c7c8258b2d42d3378be4f7738c728a07523579/src/GoTrueClient.ts#L2043
See Also
History
I originally opened this here (supabase/supabase-js#983) but moved once I discovered the
setInterval
issue.The text was updated successfully, but these errors were encountered: