Skip to content

Commit 1789eca

Browse files
committed
Add pending promise to prevent multiple token fetches
1 parent ac081a0 commit 1789eca

File tree

2 files changed

+33
-24
lines changed

2 files changed

+33
-24
lines changed

frontend/app/context/authContext.tsx

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React, { useState, useContext, useEffect } from "react";
3+
import React, { useState, useContext, useEffect, useRef } from "react";
44
import { useRouter } from "next/navigation";
55

66
interface AuthContextType {
@@ -9,7 +9,6 @@ interface AuthContextType {
99

1010
const AuthContext = React.createContext<AuthContextType | undefined>(undefined);
1111

12-
// Hook to use the Auth Context
1312
export function useAuth() {
1413
return useContext(AuthContext);
1514
}
@@ -20,38 +19,48 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
2019
const [shouldRedirect, setShouldRedirect] = useState(false);
2120

2221
async function getAccessToken(): Promise<string> {
23-
if (Date.now() >= expiryTime) {
22+
console.log(Date.now(), expiryTime);
23+
if (!accessToken || Date.now() >= expiryTime) {
2424
const token = await refreshAccessToken();
2525
return token;
2626
}
2727
return accessToken;
2828
}
2929

30-
useEffect(() => {
31-
if (typeof window === "undefined") return;
32-
getAccessToken();
33-
}, []);
34-
3530
const router = useRouter();
31+
let pendingPromise: Promise<string> | null = null;
32+
3633
async function refreshAccessToken(): Promise<string> {
37-
try {
38-
const response = await fetch("http://localhost:8000/refresh", {
39-
method: "POST",
40-
credentials: "include",
41-
});
42-
const data = await response.json();
43-
if (!response.ok) {
34+
if (pendingPromise) {
35+
return pendingPromise;
36+
}
37+
38+
pendingPromise = new Promise(async (resolve, reject) => {
39+
try {
40+
const response = await fetch("http://localhost:8000/refresh", {
41+
method: "POST",
42+
credentials: "include",
43+
});
44+
const data = await response.json();
45+
if (!response.ok) {
46+
setShouldRedirect(true);
47+
return "";
48+
}
49+
setAccessToken(data.access_token);
50+
setExpiryTime(Date.now() + 15 * 60 * 1000); // 15 minutes
51+
resolve(data.access_token);
52+
}
53+
catch (error) {
4454
setShouldRedirect(true);
45-
console.log("Failed to refresh access token");
55+
console.log("Error refreshing access token:", error);
56+
reject(error);
57+
}
58+
finally {
59+
pendingPromise = null;
4660
}
47-
setAccessToken(data.access_token);
48-
setExpiryTime(Date.now() + 15 * 60 * 1000); // 15 minutes
49-
return data.access_token;
50-
} catch (error) {
51-
setShouldRedirect(true);
52-
console.log("Error refreshing access token:", error);
53-
return "";
5461
}
62+
);
63+
return pendingPromise;
5564
}
5665

5766
useEffect(() => {

frontend/app/hooks/useWebsocketDashboard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function useWebSocketDashboard(setCircles: React.Dispatch<React.SetStateA
1717
useEffect(() => {
1818
const connectWebSocket = async () => {
1919
const token = await getAccessToken();
20-
ws.current = new WebSocket("wss://localhost:8000/ws", [token]);
20+
ws.current = new WebSocket("ws://localhost:8000/ws", [token]);
2121
ws.current.onopen = () => console.log("ws opened");
2222
ws.current.onclose = () => console.log("ws closed");
2323
const wsCurrent = ws.current;

0 commit comments

Comments
 (0)