From 9ed7a89af47d3cc8c0369f767030d36863bf36b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ianar=C3=A9=20S=C3=A9vi?= Date: Tue, 17 Feb 2026 14:45:29 +0100 Subject: [PATCH 1/2] :boom: :recycle: separate polling options --- docs/code_samples/v2_crop.txt | 4 +- docs/code_samples/v2_extraction.txt | 4 +- docs/code_samples/v2_ocr.txt | 4 +- docs/code_samples/v2_split.txt | 4 +- src/v2/client.ts | 10 ++- src/v2/client/baseParameters.ts | 45 ----------- src/v2/client/index.ts | 3 +- src/v2/client/pollingOptions.ts | 83 +++++++++++++++++--- tests/v2/{ => client}/client.integration.ts | 18 ++--- tests/v2/{ => client}/client.spec.ts | 72 +++++++++-------- tests/v2/client/pollingOptions.spec.ts | 51 ++++++++++++ tests/v2/parsing/job.spec.ts | 4 +- tests/v2/parsing/localResponse.spec.ts | 2 +- tests/v2/product/extractionParameter.spec.ts | 5 -- tests/v2/product/splitParameter.spec.ts | 5 -- 15 files changed, 194 insertions(+), 120 deletions(-) rename tests/v2/{ => client}/client.integration.ts (91%) rename tests/v2/{ => client}/client.spec.ts (73%) create mode 100644 tests/v2/client/pollingOptions.spec.ts diff --git a/docs/code_samples/v2_crop.txt b/docs/code_samples/v2_crop.txt index 4180c246..23d1ef85 100644 --- a/docs/code_samples/v2_crop.txt +++ b/docs/code_samples/v2_crop.txt @@ -12,7 +12,7 @@ const mindeeClient = new mindee.Client( ); // Set product parameters -const params = { +const productParams = { modelId: modelId, }; @@ -23,7 +23,7 @@ const inputSource = new mindee.PathInput({ inputPath: filePath }); const response = await mindeeClient.enqueueAndGetResult( mindee.product.Crop, inputSource, - params, + productParams, ); // print a string summary diff --git a/docs/code_samples/v2_extraction.txt b/docs/code_samples/v2_extraction.txt index 2e4cd51e..c705589e 100644 --- a/docs/code_samples/v2_extraction.txt +++ b/docs/code_samples/v2_extraction.txt @@ -12,7 +12,7 @@ const mindeeClient = new mindee.Client( ); // Set product parameters -const params = { +const productParams = { modelId: modelId, // Options: set to `true` or `false` to override defaults @@ -35,7 +35,7 @@ const inputSource = new mindee.PathInput({ inputPath: filePath }); const response = await mindeeClient.enqueueAndGetResult( mindee.product.Extraction, inputSource, - params, + productParams, ); // print a string summary diff --git a/docs/code_samples/v2_ocr.txt b/docs/code_samples/v2_ocr.txt index b8a029be..4750a8bf 100644 --- a/docs/code_samples/v2_ocr.txt +++ b/docs/code_samples/v2_ocr.txt @@ -12,7 +12,7 @@ const mindeeClient = new mindee.Client( ); // Set product parameters -const params = { +const productParams = { modelId: modelId, }; @@ -23,7 +23,7 @@ const inputSource = new mindee.PathInput({ inputPath: filePath }); const response = await mindeeClient.enqueueAndGetResult( mindee.product.Ocr, inputSource, - params, + productParams, ); // print a string summary diff --git a/docs/code_samples/v2_split.txt b/docs/code_samples/v2_split.txt index 3b318160..a16a300f 100644 --- a/docs/code_samples/v2_split.txt +++ b/docs/code_samples/v2_split.txt @@ -12,7 +12,7 @@ const mindeeClient = new mindee.Client( ); // Set product parameters -const params = { +const productParams = { modelId: modelId, }; @@ -23,7 +23,7 @@ const inputSource = new mindee.PathInput({ inputPath: filePath }); const response = await mindeeClient.enqueueAndGetResult( mindee.product.Split, inputSource, - params, + productParams, ); // print a string summary diff --git a/src/v2/client.ts b/src/v2/client.ts index b7c55afb..a29f2eb2 100644 --- a/src/v2/client.ts +++ b/src/v2/client.ts @@ -7,7 +7,7 @@ import { LOG_LEVELS, logger } from "@/logger.js"; import { ErrorResponse, JobResponse } from "./parsing/index.js"; import { MindeeApiV2 } from "./http/mindeeApiV2.js"; import { MindeeHttpErrorV2 } from "./http/errors.js"; -import { ValidatedPollingOptions } from "./client/index.js"; +import { PollingOptions, PollingOptionsConstructor } from "./client/index.js"; import { BaseProduct } from "@/v2/product/baseProduct.js"; /** @@ -124,6 +124,7 @@ export class Client { * @param inputSource file or URL to parse. * @param params parameters relating to prediction options. * + * @param pollingOptions * @typeParam T an extension of an `Inference`. Can be omitted as it will be inferred from the `productClass`. * @category Synchronous * @returns a `Promise` containing parsing results. @@ -132,16 +133,17 @@ export class Client { product: P, inputSource: InputSource, params: InstanceType | ConstructorParameters[0], + pollingOptions?: PollingOptionsConstructor, ): Promise> { const paramsInstance = new product.parametersClass(params); - const pollingOptions = paramsInstance.getValidatedPollingOptions(); + const pollingOptionsInstance = new PollingOptions(pollingOptions); const jobResponse: JobResponse = await this.enqueue( product, inputSource, paramsInstance ); return await this.pollForResult( - product, pollingOptions, jobResponse.job.id + product, pollingOptionsInstance, jobResponse.job.id ); } @@ -152,7 +154,7 @@ export class Client { */ protected async pollForResult

( product: typeof BaseProduct, - pollingOptions: ValidatedPollingOptions, + pollingOptions: PollingOptions, queueId: string, ): Promise> { logger.debug( diff --git a/src/v2/client/baseParameters.ts b/src/v2/client/baseParameters.ts index e2f3263c..403d4557 100644 --- a/src/v2/client/baseParameters.ts +++ b/src/v2/client/baseParameters.ts @@ -1,5 +1,3 @@ -import { ValidatedPollingOptions } from "@/v2/client/pollingOptions.js"; -import { PollingOptions } from "@/v2/index.js"; import { MindeeConfigurationError } from "@/errors/index.js"; /** @@ -9,7 +7,6 @@ export interface BaseParametersConstructor { modelId: string; alias?: string; webhookIds?: string[]; - pollingOptions?: PollingOptions; closeFile?: boolean; } @@ -46,10 +43,6 @@ export abstract class BaseParameters { * If empty, no webhooks will be used. */ webhookIds?: string[]; - /** - * Client-side polling configuration (see {@link PollingOptions}). - */ - pollingOptions?: PollingOptions; /** * By default, the file is closed once the upload is finished. * Set to `false` to keep it open. @@ -64,44 +57,6 @@ export abstract class BaseParameters { this.alias = params.alias; this.webhookIds = params.webhookIds; this.closeFile = params.closeFile; - this.pollingOptions = params.pollingOptions; - } - - /** - * Checks the values for asynchronous parsing. Returns their corrected value if they are undefined. - * @returns A valid `AsyncOptions`. - */ - getValidatedPollingOptions(): ValidatedPollingOptions { - const minDelaySec = 1; - const minInitialDelay = 1; - const minRetries = 2; - let newAsyncParams: PollingOptions; - if (this.pollingOptions === undefined) { - newAsyncParams = { - delaySec: 1.5, - initialDelaySec: 2, - maxRetries: 80 - }; - } else { - newAsyncParams = { ...this.pollingOptions }; - if ( - !newAsyncParams.delaySec || - !newAsyncParams.initialDelaySec || - !newAsyncParams.maxRetries - ) { - throw Error("Invalid polling options."); - } - if (newAsyncParams.delaySec < minDelaySec) { - throw Error(`Cannot set auto-parsing delay to less than ${minDelaySec} second(s).`); - } - if (newAsyncParams.initialDelaySec < minInitialDelay) { - throw Error(`Cannot set initial parsing delay to less than ${minInitialDelay} second(s).`); - } - if (newAsyncParams.maxRetries < minRetries) { - throw Error(`Cannot set retry to less than ${minRetries}.`); - } - } - return newAsyncParams as ValidatedPollingOptions; } /** diff --git a/src/v2/client/index.ts b/src/v2/client/index.ts index a625efc0..2cd3a706 100644 --- a/src/v2/client/index.ts +++ b/src/v2/client/index.ts @@ -1,2 +1,3 @@ -export type { PollingOptions, ValidatedPollingOptions } from "./pollingOptions.js"; +export { PollingOptions } from "./pollingOptions.js"; +export type { PollingOptionsConstructor } from "./pollingOptions.js" export { BaseParameters } from "./baseParameters.js"; diff --git a/src/v2/client/pollingOptions.ts b/src/v2/client/pollingOptions.ts index 91763284..89a42f7e 100644 --- a/src/v2/client/pollingOptions.ts +++ b/src/v2/client/pollingOptions.ts @@ -1,3 +1,23 @@ +import { MindeeConfigurationError } from "@/errors/index.js"; +import { logger } from "@/logger.js"; + +export interface TimerOptions { + ref?: boolean, + signal?: AbortSignal +} + +export interface PollingOptionsConstructor { + initialDelaySec?: number; + delaySec?: number; + maxRetries?: number; + initialTimerOptions?: TimerOptions; + recurringTimerOptions?: TimerOptions; +} + +const minInitialDelay = 1; +const minDelaySec = 1; +const minRetries = 2; + /** * Parameters for the internal polling loop in `enqueueAndGetInference()`. * @@ -24,13 +44,13 @@ * * const inference = await client.enqueueAndGetInference(inputDoc, params); */ -export interface PollingOptions { +export class PollingOptions { /** Number of seconds to wait *before the first poll*. */ - initialDelaySec?: number; + initialDelaySec: number; /** Interval in seconds between two consecutive polls. */ - delaySec?: number; + delaySec: number; /** Maximum number of polling attempts (including the first one). */ - maxRetries?: number; + maxRetries: number; /** Options passed to the initial `setTimeout()`. */ initialTimerOptions?: { ref?: boolean, @@ -40,11 +60,56 @@ export interface PollingOptions { recurringTimerOptions?: { ref?: boolean, signal?: AbortSignal + }; + + constructor(params?: PollingOptionsConstructor) { + if (!params) { + params = {}; + } + if (!params.initialDelaySec) { + this.initialDelaySec = 2; + } else { + this.initialDelaySec = params.initialDelaySec; + } + if (!params.delaySec) { + this.delaySec = 1.5; + } else { + this.delaySec = params.delaySec; + } + if (!params.maxRetries) { + this.maxRetries = 80; + } else { + this.maxRetries = params.maxRetries; + } + if (params.initialTimerOptions) { + this.initialTimerOptions = params.initialTimerOptions; + } + if (params.recurringTimerOptions) { + this.recurringTimerOptions = params.recurringTimerOptions; + } + this.validateOptions(); + logger.debug(`Polling options initialized: ${this.toString()}`); } -} -export interface ValidatedPollingOptions extends PollingOptions { - initialDelaySec: number; - delaySec: number; - maxRetries: number; + validateOptions() { + if (this.delaySec < minDelaySec) { + throw new MindeeConfigurationError( + `Cannot set auto-parsing delay to less than ${minDelaySec} second(s).` + ); + } + if (this.initialDelaySec < minInitialDelay) { + throw new MindeeConfigurationError( + `Cannot set initial parsing delay to less than ${minInitialDelay} second(s).` + ); + } + if (this.maxRetries < minRetries) { + throw new MindeeConfigurationError( + `Cannot set retry to less than ${minRetries}.` + ); + } + } + + toString(): string { + return `{ initialDelaySec: ${this.initialDelaySec}, delaySec: ${this.delaySec}, maxRetries: ${this.maxRetries} }`; + } } diff --git a/tests/v2/client.integration.ts b/tests/v2/client/client.integration.ts similarity index 91% rename from tests/v2/client.integration.ts rename to tests/v2/client/client.integration.ts index c14626f3..56f29dd6 100644 --- a/tests/v2/client.integration.ts +++ b/tests/v2/client/client.integration.ts @@ -15,7 +15,7 @@ import { import { SimpleField } from "@/v2/parsing/inference/field/index.js"; import { MindeeHttpErrorV2 } from "@/v2/http/index.js"; import * as fs from "node:fs"; -import { RESOURCE_PATH, V2_PRODUCT_PATH } from "../index.js"; +import { RESOURCE_PATH, V2_PRODUCT_PATH } from "../../index.js"; import { Extraction } from "@/v2/product/index.js"; function check422(err: unknown) { @@ -37,7 +37,7 @@ function checkEmptyActiveOptions(inference: ExtractionInference) { assert.equal(inference.activeOptions?.textContext, false); } -describe("MindeeV2 – Client Integration Tests", () => { +describe("MindeeV2 – Integration - Client", () => { let client: Client; let modelId: string; @@ -73,7 +73,7 @@ describe("MindeeV2 – Client Integration Tests", () => { dataSchemaReplace = fs.readFileSync(dataSchemaReplacePath).toString(); }); - it("Empty, multi-page PDF – PathInput - enqueueAndGetResult must succeed", async () => { + it("enqueueAndGetResult must succeed: Empty, multi-page PDF – PathInput", async () => { const source = new PathInput({ inputPath: emptyPdfPath }); const params = { modelId, @@ -100,7 +100,7 @@ describe("MindeeV2 – Client Integration Tests", () => { checkEmptyActiveOptions(inference); }).timeout(60000); - it("Filled, single-page image – PathInput - enqueueAndGetResult must succeed", async () => { + it("enqueueAndGetResult must succeed: Filled, single-page image – PathInput", async () => { const source = new PathInput({ inputPath: sampleImagePath }); const params = { modelId, @@ -139,7 +139,7 @@ describe("MindeeV2 – Client Integration Tests", () => { assert.equal(inference.result.rawText?.pages.length, 1); }).timeout(120000); - it("Filled, single-page image – Base64Input - enqueueAndGetResult must succeed", async () => { + it("enqueueAndGetResult must succeed: Filled, single-page image – Base64Input", async () => { const data = fs.readFileSync(sampleBase64Path, "utf8"); const source = new Base64Input({ inputString: data, filename: "receipt.jpg" }); const params = { @@ -170,7 +170,7 @@ describe("MindeeV2 – Client Integration Tests", () => { checkEmptyActiveOptions(inference); }).timeout(120000); - it("Invalid model ID – enqueue must raise 422", async () => { + it("enqueue must raise 422: Invalid model ID", async () => { const source = new PathInput({ inputPath: emptyPdfPath }); const badParams = { modelId: "00000000-0000-0000-0000-000000000000" }; @@ -182,7 +182,7 @@ describe("MindeeV2 – Client Integration Tests", () => { } }).timeout(60000); - it("Invalid job ID – getInference must raise 422", async () => { + it("getResult must raise 422: Invalid job ID", async () => { try { await client.getResult( Extraction, @@ -194,7 +194,7 @@ describe("MindeeV2 – Client Integration Tests", () => { } }).timeout(60000); - it("HTTPS URL – enqueueAndGetResult must succeed", async () => { + it("enqueueAndGetResult must succeed: HTTPS URL", async () => { const url = process.env.MINDEE_V2_SE_TESTS_BLANK_PDF_URL ?? "error-no-url-found"; const source = new UrlInput({ url }); const params = new ExtractionParameters({ @@ -213,7 +213,7 @@ describe("MindeeV2 – Client Integration Tests", () => { assert.ok(response.inference instanceof ExtractionInference); }).timeout(60000); - it("Data Schema Override - Overrides the data schema successfully", async () => { + it("should override the data schema successfully", async () => { const source = new PathInput({ inputPath: emptyPdfPath }); const params = new ExtractionParameters({ modelId, diff --git a/tests/v2/client.spec.ts b/tests/v2/client/client.spec.ts similarity index 73% rename from tests/v2/client.spec.ts rename to tests/v2/client/client.spec.ts index fb2651f6..095d8672 100644 --- a/tests/v2/client.spec.ts +++ b/tests/v2/client/client.spec.ts @@ -2,12 +2,11 @@ import path from "path"; import assert from "node:assert/strict"; import { after, before, beforeEach, describe, it } from "node:test"; import { MockAgent, setGlobalDispatcher } from "undici"; +import fs from "node:fs/promises"; -import { Client, PathInput } from "@/index.js"; +import { Client, PathInput, product } from "@/index.js"; import { MindeeHttpErrorV2 } from "@/v2/http/index.js"; -import { RESOURCE_PATH, V2_RESOURCE_PATH } from "../index.js"; -import fs from "node:fs/promises"; -import { Crop, Extraction } from "@/v2/product/index.js"; +import { RESOURCE_PATH, V2_RESOURCE_PATH } from "../../index.js"; const mockAgent = new MockAgent(); setGlobalDispatcher(mockAgent); @@ -42,9 +41,11 @@ async function setAllInterceptors(): Promise { ); } -describe("MindeeV2 - ClientV2", () => { +describe("MindeeV2 - Client", () => { const fileTypesDir = path.join(RESOURCE_PATH, "file_types"); + let client: Client; + before(() => { dummyEnvvars(); }); @@ -54,13 +55,12 @@ describe("MindeeV2 - ClientV2", () => { delete process.env.MINDEE_V2_API_HOST; }); - describe("Client configured via environment variables", () => { - let client: Client; + beforeEach(async () => { + await setAllInterceptors(); + client = new Client({ apiKey: "dummy", debug: true, dispatcher: mockAgent }); + }); - beforeEach(async () => { - await setAllInterceptors(); - client = new Client({ apiKey: "dummy", debug: true, dispatcher: mockAgent }); - }); + describe("Client configured via environment variables", () => { it("inherits base URL, token & headers from the env / options", () => { const api = (client as any).mindeeApi; @@ -70,40 +70,51 @@ describe("MindeeV2 - ClientV2", () => { assert.match(api.settings.baseHeaders["User-Agent"], /mindee/i); }); - it("enqueue(path) on extraction rejects with MindeeHttpErrorV2 on 400", async () => { + }); + + describe("enqueue(path)", () => { + it("extraction rejects with MindeeHttpErrorV2 on 400", async () => { const filePath = path.join(fileTypesDir, "receipt.jpg"); const inputDoc = new PathInput({ inputPath: filePath }); await assert.rejects( - client.enqueue(Extraction, inputDoc, { modelId: "dummy-model", textContext: "hello" }), + client.enqueue( + product.Extraction, inputDoc, { modelId: "dummy-model", textContext: "hello" } + ), (error: any) => { assert.strictEqual(error instanceof MindeeHttpErrorV2, true); assert.strictEqual(error.status, 400); + assert.strictEqual(error.detail, "forced failure from test"); return true; } ); }); - it("enqueue(path) on crop rejects with MindeeHttpErrorV2 on 400", async () => { + it("crop rejects with MindeeHttpErrorV2 on 400", async () => { const filePath = path.join(fileTypesDir, "receipt.jpg"); const inputDoc = new PathInput({ inputPath: filePath }); await assert.rejects( - client.enqueue(Crop, inputDoc, { modelId: "dummy-model" }), + client.enqueue( + product.Crop, inputDoc, { modelId: "dummy-model" } + ), (error: any) => { assert.strictEqual(error instanceof MindeeHttpErrorV2, true); assert.strictEqual(error.status, 400); + assert.strictEqual(error.detail, "forced failure from test"); return true; } ); }); + }); - it("enqueueAndGetResult(path) on extraction rejects with MindeeHttpErrorV2 on 400", async () => { + describe("enqueueAndGetResult(path)", () => { + it("no polling options rejects with MindeeHttpErrorV2 on 400", async () => { const filePath = path.join(fileTypesDir, "receipt.jpg"); const inputDoc = new PathInput({ inputPath: filePath }); await assert.rejects( client.enqueueAndGetResult( - Extraction, + product.Extraction, inputDoc, { modelId: "dummy-model", rag: false } ), @@ -115,28 +126,27 @@ describe("MindeeV2 - ClientV2", () => { ); }); - it("bubble-up HTTP errors with details", async () => { - const input = new PathInput({ - inputPath: path.join( - V2_RESOURCE_PATH, - "products", - "extraction", - "financial_document", - "default_sample.jpg" - ), - }); + it("with polling options rejects with MindeeHttpErrorV2 on 400", async () => { + const filePath = path.join(fileTypesDir, "receipt.jpg"); + const inputDoc = new PathInput({ inputPath: filePath }); await assert.rejects( - client.enqueue(Extraction, input, { modelId: "dummy-model" }), + client.enqueueAndGetResult( + product.Extraction, + inputDoc, + { modelId: "dummy-model", rag: false }, + { initialDelaySec: 2, maxRetries: 100 } + ), (error: any) => { - assert.ok(error instanceof MindeeHttpErrorV2); + assert.strictEqual(error instanceof MindeeHttpErrorV2, true); assert.strictEqual(error.status, 400); - assert.strictEqual(error.detail, "forced failure from test"); return true; } ); }); + }); - it("getJob(jobId) returns a fully-formed JobResponse", async () => { + describe("getJob(jobId)", () => { + it("returns a fully-formed JobResponse", async () => { const resp = await client.getJob( "12345678-1234-1234-1234-123456789ABC" ); diff --git a/tests/v2/client/pollingOptions.spec.ts b/tests/v2/client/pollingOptions.spec.ts new file mode 100644 index 00000000..3b3ddf1b --- /dev/null +++ b/tests/v2/client/pollingOptions.spec.ts @@ -0,0 +1,51 @@ +import { describe, it } from "node:test"; +import assert from "node:assert/strict"; +import { PollingOptions } from "@/v2/client/index.js"; +import { MindeeConfigurationError } from "@/errors/index.js"; + +describe("MindeeV2 - Polling Options", () => { + + it("should provide sensible defaults", () => { + const pollingOptions1 = new PollingOptions(); + assert.strictEqual(pollingOptions1.delaySec, 1.5); + assert.strictEqual(pollingOptions1.initialDelaySec, 2); + assert.strictEqual(pollingOptions1.maxRetries, 80); + + const pollingOptions2 = new PollingOptions({}); + assert.strictEqual(pollingOptions2.delaySec, 1.5); + assert.strictEqual(pollingOptions2.initialDelaySec, 2); + assert.strictEqual(pollingOptions2.maxRetries, 80); + }); + + it("should allow custom values", () => { + const pollingOptions = new PollingOptions({ + delaySec: 2, + initialDelaySec: 5, + maxRetries: 90, + }); + assert.strictEqual(pollingOptions.delaySec, 2); + assert.strictEqual(pollingOptions.initialDelaySec, 5); + assert.strictEqual(pollingOptions.maxRetries, 90); + }); + + it("should disallow ridiculous values", () => { + assert.throws( + () => { + new PollingOptions({ delaySec: 0.01 }); + }, + MindeeConfigurationError + ); + assert.throws( + () => { + new PollingOptions({ initialDelaySec: 0.01 }); + }, + MindeeConfigurationError + ); + assert.throws( + () => { + new PollingOptions({ maxRetries: 1 }); + }, + MindeeConfigurationError + ); + }); +}); diff --git a/tests/v2/parsing/job.spec.ts b/tests/v2/parsing/job.spec.ts index 5f4ff498..17da3916 100644 --- a/tests/v2/parsing/job.spec.ts +++ b/tests/v2/parsing/job.spec.ts @@ -18,7 +18,7 @@ async function loadV2Job(resourcePath: string): Promise { } describe("MindeeV2 - Job Response", async () => { - describe("OK", async () => { + describe("Success", async () => { it("should load when status is Processing", async () => { const response = await loadV2Job( path.join(jobPath, "ok_processing.json") @@ -27,7 +27,7 @@ describe("MindeeV2 - Job Response", async () => { assert.strictEqual(response.job.error, undefined); }); }); - describe("Fail", async () => { + describe("Failure", async () => { it("should load with 422 error", async () => { const response = await loadV2Job( path.join(jobPath, "fail_422.json") diff --git a/tests/v2/parsing/localResponse.spec.ts b/tests/v2/parsing/localResponse.spec.ts index 8318f6a6..798b21b3 100644 --- a/tests/v2/parsing/localResponse.spec.ts +++ b/tests/v2/parsing/localResponse.spec.ts @@ -48,7 +48,7 @@ describe("MindeeV2 - Load Local Response", () => { assert.strictEqual(JSON.stringify(response.getRawHttp()), JSON.stringify(JSON.parse(fileObj))); }); - it("loading an inference works on catalog model", async () => { + it("should load an inference of a catalog model", async () => { const jsonPath = path.join( V2_PRODUCT_PATH, "extraction", diff --git a/tests/v2/product/extractionParameter.spec.ts b/tests/v2/product/extractionParameter.spec.ts index d85479ec..84427a28 100644 --- a/tests/v2/product/extractionParameter.spec.ts +++ b/tests/v2/product/extractionParameter.spec.ts @@ -20,11 +20,6 @@ describe("MindeeV2 - Extraction Parameter", () => { modelId: modelIdValue, }); assert.strictEqual(paramsInstance.modelId, modelIdValue); - assert.deepStrictEqual(paramsInstance.getValidatedPollingOptions(), { - delaySec: 1.5, - initialDelaySec: 2, - maxRetries: 80 - }); }); }); diff --git a/tests/v2/product/splitParameter.spec.ts b/tests/v2/product/splitParameter.spec.ts index 7da02ba9..c35c0311 100644 --- a/tests/v2/product/splitParameter.spec.ts +++ b/tests/v2/product/splitParameter.spec.ts @@ -12,11 +12,6 @@ describe("MindeeV2 - Split Parameter", () => { modelId: modelIdValue, }); assert.strictEqual(paramsInstance.modelId, modelIdValue); - assert.deepStrictEqual(paramsInstance.getValidatedPollingOptions(), { - delaySec: 1.5, - initialDelaySec: 2, - maxRetries: 80 - }); }); }); From fa6bdb5d7e4180ba19f7defadf879a737ed59cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ianar=C3=A9=20S=C3=A9vi?= Date: Tue, 17 Feb 2026 14:59:33 +0100 Subject: [PATCH 2/2] error message --- src/v2/client.ts | 7 +++---- src/v2/client/index.ts | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/v2/client.ts b/src/v2/client.ts index a29f2eb2..7e3dfed1 100644 --- a/src/v2/client.ts +++ b/src/v2/client.ts @@ -124,7 +124,7 @@ export class Client { * @param inputSource file or URL to parse. * @param params parameters relating to prediction options. * - * @param pollingOptions + * @param pollingOptions options for the polling loop, see {@link PollingOptions}. * @typeParam T an extension of an `Inference`. Can be omitted as it will be inferred from the `productClass`. * @category Synchronous * @returns a `Promise` containing parsing results. @@ -195,9 +195,8 @@ export class Client { } throw new MindeeError( - "Asynchronous parsing request timed out after " + - pollingOptions.delaySec * retryCounter + - " seconds" + `Polling failed to retrieve a result after ${retryCounter} attempts. ` + + "You can increase poll attempts by passing the pollingOptions argument to enqueueAndGetResult()" ); } } diff --git a/src/v2/client/index.ts b/src/v2/client/index.ts index 2cd3a706..9793b752 100644 --- a/src/v2/client/index.ts +++ b/src/v2/client/index.ts @@ -1,3 +1,3 @@ export { PollingOptions } from "./pollingOptions.js"; -export type { PollingOptionsConstructor } from "./pollingOptions.js" +export type { PollingOptionsConstructor } from "./pollingOptions.js"; export { BaseParameters } from "./baseParameters.js";