Skip to content

Commit 7e5e1be

Browse files
Configure safeFetch to use a 120-second dynamic timeout for heavy upload and grading requests to resolve aborted signal exceptions
1 parent 7d5fb17 commit 7e5e1be

1 file changed

Lines changed: 12 additions & 8 deletions

File tree

src/app/context/AuthContext.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ import { supabase } from "../../lib/supabaseClient";
66
const API_BASE = process.env.NEXT_PUBLIC_API_URL || "https://edeziav2.onrender.com/api/v1";
77

88
const safeFetch = async (url: string, options: RequestInit = {}): Promise<Response> => {
9+
const isHeavyRequest = url.includes("/upload") || url.includes("/submissions") || url.includes("/runs") || url.includes("/grade");
10+
const defaultTimeout = isHeavyRequest ? 120000 : 8000; // 120 seconds for AI/upload tasks, 8 seconds for fast auth
11+
const timeoutMs = (options as any).timeout !== undefined ? (options as any).timeout : defaultTimeout;
12+
913
const controller = new AbortController();
10-
const id = setTimeout(() => controller.abort(), 6000); // 6 seconds timeout
14+
const id = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
1115

1216
const fetchOptions = {
1317
...options,
@@ -21,7 +25,7 @@ const safeFetch = async (url: string, options: RequestInit = {}): Promise<Respon
2125
const rest = parts.slice(1).join(",");
2226

2327
// Resolve path from secondary base dynamically
24-
const secondBase = "https://edeziav2.onrender.com/api/v1";
28+
const secondBase = "https://edeziav2.onrender.com/api/v1";
2529
let path = "";
2630
if (rest.startsWith(secondBase)) {
2731
path = rest.substring(secondBase.length);
@@ -37,29 +41,29 @@ const safeFetch = async (url: string, options: RequestInit = {}): Promise<Respon
3741

3842
try {
3943
const res = await fetch(url1, fetchOptions);
40-
clearTimeout(id);
44+
if (id) clearTimeout(id);
4145
return res;
4246
} catch (err) {
4347
console.warn(`Local API offline at ${url1}, falling back to remote production at ${url2}`, err);
4448

4549
// Reset timeout for fallback fetch
4650
const fallbackController = new AbortController();
47-
const fallbackId = setTimeout(() => fallbackController.abort(), 6000);
51+
const fallbackId = timeoutMs > 0 ? setTimeout(() => fallbackController.abort(), timeoutMs) : null;
4852
try {
4953
const res = await fetch(url2, { ...options, signal: fallbackController.signal });
50-
clearTimeout(fallbackId);
54+
if (fallbackId) clearTimeout(fallbackId);
5155
return res;
5256
} catch (fallbackErr) {
53-
clearTimeout(fallbackId);
57+
if (fallbackId) clearTimeout(fallbackId);
5458
throw fallbackErr;
5559
}
5660
}
5761
}
5862
const res = await fetch(url, fetchOptions);
59-
clearTimeout(id);
63+
if (id) clearTimeout(id);
6064
return res;
6165
} catch (error) {
62-
clearTimeout(id);
66+
if (id) clearTimeout(id);
6367
throw error;
6468
}
6569
};

0 commit comments

Comments
 (0)