diff --git a/.changeset/four-baboons-behave.md b/.changeset/four-baboons-behave.md new file mode 100644 index 00000000000..63c51a44c7e --- /dev/null +++ b/.changeset/four-baboons-behave.md @@ -0,0 +1,5 @@ +--- +'@firebase/vertexai': patch +--- + +Clear fetch timeout after request completion. Fixes an issue that caused Node scripts to hang due to a pending timeout. diff --git a/packages/vertexai/src/requests/request.ts b/packages/vertexai/src/requests/request.ts index 411bad859f0..98c3d7273dd 100644 --- a/packages/vertexai/src/requests/request.ts +++ b/packages/vertexai/src/requests/request.ts @@ -116,7 +116,6 @@ export async function constructRequest( return { url: url.toString(), fetchOptions: { - ...buildFetchOptions(requestOptions), method: 'POST', headers: await getHeaders(url), body @@ -134,6 +133,7 @@ export async function makeRequest( ): Promise { const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); let response; + let fetchTimeoutId: string | number | NodeJS.Timeout | undefined; try { const request = await constructRequest( model, @@ -143,6 +143,15 @@ export async function makeRequest( body, requestOptions ); + // Timeout is 180s by default + const timeoutMillis = + requestOptions?.timeout !== undefined + ? requestOptions.timeout + : 180 * 1000; + const abortController = new AbortController(); + fetchTimeoutId = setTimeout(() => abortController.abort(), timeoutMillis); + request.fetchOptions.signal = abortController.signal; + response = await fetch(request.url, request.fetchOptions); if (!response.ok) { let message = ''; @@ -211,24 +220,10 @@ export async function makeRequest( } throw err; + } finally { + if (fetchTimeoutId) { + clearTimeout(fetchTimeoutId); + } } return response; } - -/** - * Generates the request options to be passed to the fetch API. - * @param requestOptions - The user-defined request options. - * @returns The generated request options. - */ -function buildFetchOptions(requestOptions?: RequestOptions): RequestInit { - const fetchOptions = {} as RequestInit; - let timeoutMillis = 180 * 1000; // default: 180 s - if (requestOptions?.timeout && requestOptions?.timeout >= 0) { - timeoutMillis = requestOptions.timeout; - } - const abortController = new AbortController(); - const signal = abortController.signal; - setTimeout(() => abortController.abort(), timeoutMillis); - fetchOptions.signal = signal; - return fetchOptions; -}