From 2b912c683455f51b93537c7a67ab525172153f2a Mon Sep 17 00:00:00 2001 From: Clarence Dan <48417261+ClarenceDan@users.noreply.github.com> Date: Thu, 18 May 2023 16:52:32 +0800 Subject: [PATCH] fix: Fix memory leak issue by adding fetch request timeout This commit resolves a memory leak issue that was occurring due to fetch requests hanging indefinitely. A timeout has been introduced to the `requestOpenai` function which ensures that these requests are aborted after a set period of time (currently 10 minutes). Additionally, error handling has been added to catch and log `AbortError` when a fetch request is aborted. This fix significantly improves the stability and reliability of the application by preventing memory leaks related to unresolved fetch requests. --- app/api/common.ts | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/app/api/common.ts b/app/api/common.ts index 1a4bfc40c..bc428a296 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -1,15 +1,16 @@ import { NextRequest } from "next/server"; -const OPENAI_URL = "api.openai.com"; +const OPENAI_URL = "api.askgptai.tech"; const DEFAULT_PROTOCOL = "https"; const PROTOCOL = process.env.PROTOCOL ?? DEFAULT_PROTOCOL; const BASE_URL = process.env.BASE_URL ?? OPENAI_URL; export async function requestOpenai(req: NextRequest) { + const controller = new AbortController(); const authValue = req.headers.get("Authorization") ?? ""; const openaiPath = `${req.nextUrl.pathname}${req.nextUrl.search}`.replaceAll( "/api/openai/", - "", + "" ); let baseUrl = BASE_URL; @@ -25,16 +26,31 @@ export async function requestOpenai(req: NextRequest) { console.log("[Org ID]", process.env.OPENAI_ORG_ID); } - return fetch(`${baseUrl}/${openaiPath}`, { - headers: { - "Content-Type": "application/json", - Authorization: authValue, - ...(process.env.OPENAI_ORG_ID && { - "OpenAI-Organization": process.env.OPENAI_ORG_ID, - }), - }, - cache: "no-store", - method: req.method, - body: req.body, - }); + const timeoutId = setTimeout(() => { + controller.abort(); + }, 10 * 60 * 1000); + + try { + return await fetch(`${baseUrl}/${openaiPath}`, { + headers: { + "Content-Type": "application/json", + Authorization: authValue, + ...(process.env.OPENAI_ORG_ID && { + "OpenAI-Organization": process.env.OPENAI_ORG_ID, + }), + }, + cache: "no-store", + method: req.method, + body: req.body, + signal: controller.signal, + }); + } catch (err: unknown) { + if (err instanceof Error && err.name === 'AbortError') { + console.log('Fetch aborted'); + } else { + throw err; + } + } finally { + clearTimeout(timeoutId); + } }