diff --git a/src/index.ts b/src/index.ts index 0fe70f9..80fe8f1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,17 +42,13 @@ export class ZenRows { this.clientConfig = clientConfig; const retries = this.clientConfig.retries ?? 0; - this.queue = fastq.promise( - this, - this.worker, - this.clientConfig.concurrency ?? 5, - ); + this.queue = fastq.promise(this, this.worker, this.clientConfig.concurrency ?? 5); this.fetchWithRetry = fetchRetry(fetch, { retryDelay: (attempt) => 2 ** attempt * 1000, // retryOn: [422, 503, 504], retryOn: (attempt, error, response) => { - if (attempt > retries) { + if (attempt >= retries) { return false; } @@ -73,7 +69,7 @@ export class ZenRows { public get( url: string, config?: ZenRowsConfig, - { headers = {} }: { headers?: Headers } = {}, + { headers = {} }: { headers?: Headers } = {} ): Promise { return this.queue.push({ url, config, headers }); } @@ -83,7 +79,7 @@ export class ZenRows { config?: ZenRowsConfig, { headers = {}, data = {} }: { headers?: Headers; data?: unknown } = { headers: { "Content-Type": "application/x-www-form-urlencoded" }, - }, + } ): Promise { const normalizedHeaders = Object.keys(headers).reduce( (acc: { [key: string]: string }, key: string) => { @@ -97,7 +93,7 @@ export class ZenRows { } return acc; }, - {}, + {} ); return this.queue.push({ @@ -160,10 +156,7 @@ export class ZenRows { } } - const response = await this.fetchWithRetry( - `${API_URL}?${params.toString()}`, - fetchOptions, - ); + const response = await this.fetchWithRetry(`${API_URL}?${params.toString()}`, fetchOptions); return response; } diff --git a/tests/retry-count.test.ts b/tests/retry-count.test.ts new file mode 100644 index 0000000..e48088b --- /dev/null +++ b/tests/retry-count.test.ts @@ -0,0 +1,30 @@ +import { describe, test, expect } from "vitest"; +import { ZenRows } from "../src"; +import { server } from "./_setup"; +import { HttpResponse, http } from "msw"; + +describe("retryOn off-by-one fix", () => { + test.each([ + { retries: 0, expectedCalls: 1 }, + { retries: 1, expectedCalls: 2 }, + { retries: 2, expectedCalls: 3 }, + ])( + "retries: $retries should make exactly $expectedCalls fetch call(s) on 422", + async ({ retries, expectedCalls }) => { + let fetchCount = 0; + + server.use( + http.get("https://api.zenrows.com/v1/", () => { + fetchCount++; + return new HttpResponse("Could Not Get Content", { status: 422 }); + }) + ); + + const client = new ZenRows("API_KEY", { retries }); + const response = await client.get("https://example.com"); + + expect(response.status).toBe(422); + expect(fetchCount).toBe(expectedCalls); + } + ); +});