From c3802ac1ef6f943f1a4270fba44cdd1284a9167a Mon Sep 17 00:00:00 2001 From: staticdev Date: Wed, 12 Aug 2026 15:30:53 +0000 Subject: [PATCH] fix(frontend): remove Automate operation timeout (#7082) # Description of Changes Remove the hard-coded five-minute client-side timeout from Automate operations. - Remove `AUTOMATION_CONSTANTS.OPERATION_TIMEOUT`. - Let normal Automate requests use the API client's default no-timeout behavior, matching regular tool execution. - Preserve an explicitly supplied `AutomationProcessingOptions.timeout` without applying a finite default. - Add regression coverage verifying that Automate does not send a client-side timeout by default. Large PDF operations such as compression can legitimately take more than five minutes. Previously, Axios aborted the frontend request after 300,000 ms even when the server and reverse proxy allowed the operation to continue. The backend could continue processing while the frontend discarded the result. No significant implementation challenges were encountered. Closes #7081 ## Testing The following frontend checks passed: - Proprietary frontend TypeScript typecheck - ESLint with zero warnings - Circular dependency check - Theme colour lint - Prettier formatting check - Focused `automationExecutor.test.ts` regression test - Complete Vitest suite: 165 test files and 1,354 tests passed --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (not applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (not applicable; no user-facing configuration changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (not applicable) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) (not applicable) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (not applicable; no visual changes) ### Testing (if applicable) - [ ] I have run `task check` to verify linters, typechecks, and tests pass - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing) for more details. Co-authored-by: Reece Browne <74901996+reecebrowne@users.noreply.github.com> --- .../editor/src/core/constants/automation.ts | 3 -- .../src/core/utils/automationExecutor.test.ts | 54 ++++++++++++++++++- .../src/core/utils/automationExecutor.ts | 1 - .../src/core/utils/automationFileProcessor.ts | 4 +- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/frontend/editor/src/core/constants/automation.ts b/frontend/editor/src/core/constants/automation.ts index 56fc7ee35f..a3fa1f5a82 100644 --- a/frontend/editor/src/core/constants/automation.ts +++ b/frontend/editor/src/core/constants/automation.ts @@ -3,9 +3,6 @@ */ export const AUTOMATION_CONSTANTS = { - // Timeouts - OPERATION_TIMEOUT: 300000, // 5 minutes in milliseconds - // Default values DEFAULT_TOOL_COUNT: 2, MIN_TOOL_COUNT: 2, diff --git a/frontend/editor/src/core/utils/automationExecutor.test.ts b/frontend/editor/src/core/utils/automationExecutor.test.ts index 5cff7b2ab0..2eb2cd1d19 100644 --- a/frontend/editor/src/core/utils/automationExecutor.test.ts +++ b/frontend/editor/src/core/utils/automationExecutor.test.ts @@ -1,5 +1,19 @@ -import { describe, expect, test } from "vitest"; -import { processMultiFileResponse } from "@app/utils/automationExecutor"; +import { beforeEach, describe, expect, type Mock, test, vi } from "vitest"; +import apiClient from "@app/services/apiClient"; +import type { ToolRegistry } from "@app/data/toolsTaxonomy"; +import { ToolType } from "@app/hooks/tools/shared/useToolOperation"; +import { + executeToolOperation, + processMultiFileResponse, +} from "@app/utils/automationExecutor"; + +vi.mock("@app/services/apiClient", () => ({ + default: { + post: vi.fn(), + }, +})); + +const mockedApiClient = vi.mocked(apiClient); // Regression coverage for the automation-side mirror of the merge bug: // non-canonical Content-Types previously misrouted a PDF into ZIP extraction @@ -56,3 +70,39 @@ describe("processMultiFileResponse (automation execution)", () => { expect(result[0].name).not.toMatch(/\.zip$/); }); }); + +describe("executeToolOperation (automation execution)", () => { + beforeEach(() => { + vi.clearAllMocks(); + (mockedApiClient.post as Mock).mockResolvedValue({ + data: new Blob([PDF_BYTES], { type: "application/pdf" }), + headers: { "content-type": "application/pdf" }, + }); + }); + + test("does not impose a client-side operation timeout", async () => { + const toolRegistry = { + compress: { + operationConfig: { + operationType: "compress", + toolType: ToolType.singleFile, + endpoint: "/api/v1/misc/compress-pdf", + defaultParameters: {}, + buildFormData: (_parameters: unknown, file: File) => { + const formData = new FormData(); + formData.append("fileInput", file); + return formData; + }, + }, + }, + } as unknown as ToolRegistry; + + await executeToolOperation("compress", {}, inputFiles, toolRegistry); + + expect(mockedApiClient.post).toHaveBeenCalledWith( + "/api/v1/misc/compress-pdf", + expect.any(FormData), + { responseType: "blob" }, + ); + }); +}); diff --git a/frontend/editor/src/core/utils/automationExecutor.ts b/frontend/editor/src/core/utils/automationExecutor.ts index f47778deda..7855bc25e7 100644 --- a/frontend/editor/src/core/utils/automationExecutor.ts +++ b/frontend/editor/src/core/utils/automationExecutor.ts @@ -65,7 +65,6 @@ const executeApiRequest = async ( ): Promise => { const response = await apiClient.post(endpoint, formData, { responseType: "blob", - timeout: AUTOMATION_CONSTANTS.OPERATION_TIMEOUT, }); return await processMultiFileResponse( diff --git a/frontend/editor/src/core/utils/automationFileProcessor.ts b/frontend/editor/src/core/utils/automationFileProcessor.ts index 5326abcdcc..6ff5a558be 100644 --- a/frontend/editor/src/core/utils/automationFileProcessor.ts +++ b/frontend/editor/src/core/utils/automationFileProcessor.ts @@ -97,7 +97,7 @@ export class AutomationFileProcessor { try { const response = await apiClient.post(endpoint, formData, { responseType: options.responseType || "blob", - timeout: options.timeout || AUTOMATION_CONSTANTS.OPERATION_TIMEOUT, + ...(options.timeout !== undefined ? { timeout: options.timeout } : {}), }); if (response.status !== 200) { @@ -143,7 +143,7 @@ export class AutomationFileProcessor { try { const response = await apiClient.post(endpoint, formData, { responseType: options.responseType || "blob", - timeout: options.timeout || AUTOMATION_CONSTANTS.OPERATION_TIMEOUT, + ...(options.timeout !== undefined ? { timeout: options.timeout } : {}), }); if (response.status !== 200) {