fix(auth): prevent concurrent dispatch deadlocks and add timeout to UserContext
This commit is contained in:
parent
6640162d4d
commit
8502a82b5a
1 changed files with 23 additions and 7 deletions
|
|
@ -87,13 +87,30 @@ export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
let isFetching = false; // Prevent concurrent deadlocks
|
||||||
|
|
||||||
const handleSession = async (session: any) => {
|
const handleSession = async (session: any) => {
|
||||||
|
if (isFetching) return;
|
||||||
|
isFetching = true;
|
||||||
|
|
||||||
if (session?.user) {
|
if (session?.user) {
|
||||||
await fetchUserProfile(session.user.id, session.user.email);
|
// Promise.race to guarantee we escape infinite loading if Supabase POST/GET hangs
|
||||||
|
const timeout = new Promise<void>((_, reject) => setTimeout(() => reject(new Error("DB Timeout")), 8000));
|
||||||
|
try {
|
||||||
|
await Promise.race([
|
||||||
|
fetchUserProfile(session.user.id, session.user.email),
|
||||||
|
timeout
|
||||||
|
]);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("UserContext HandleSession Error:", e);
|
||||||
|
if (mounted) setLoading(false);
|
||||||
|
} finally {
|
||||||
|
isFetching = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setUser(null);
|
setUser(null);
|
||||||
setLoading(false);
|
if (mounted) setLoading(false);
|
||||||
|
isFetching = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -110,21 +127,20 @@ export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||||
setIsAdminView(false);
|
setIsAdminView(false);
|
||||||
setIsProfessionalView(false);
|
setIsProfessionalView(false);
|
||||||
setIsCompletingProfile(false);
|
setIsCompletingProfile(false);
|
||||||
setLoading(false);
|
if (mounted) setLoading(false);
|
||||||
|
isFetching = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize session manually in case INITIAL_SESSION doesn't trigger
|
// Fallback for when "INITIAL_SESSION" gets completely skipped by Supabase JS on load
|
||||||
// (sometimes needed depending on supabase-js version and local storage state)
|
|
||||||
supabase.auth.getSession().then(({ data: { session }, error }) => {
|
supabase.auth.getSession().then(({ data: { session }, error }) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("UserContext: Falha na sessão inicial", error);
|
console.error("UserContext: Falha na sessão inicial", error);
|
||||||
if (mounted) setLoading(false);
|
if (mounted) setLoading(false);
|
||||||
} else if (session) {
|
} else if (session) {
|
||||||
// Handled gracefully: forces profile fetch if session exists but events failed
|
// If there's a session but events haven't fired or were skipped, gently process it
|
||||||
handleSession(session);
|
handleSession(session);
|
||||||
} else {
|
} else {
|
||||||
// Se não há sessão e onAuthStateChange não disparou INITIAL_SESSION
|
|
||||||
if (mounted) setLoading(false);
|
if (mounted) setLoading(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue