mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 05:45:04 +03:00
109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
/**
|
|
* Unit tests for the pure `syncInChunksWithSpacing` helper (#6916).
|
|
*
|
|
* Proves the chunking/spacing contract in isolation — no DB, no network —
|
|
* before it is wired into `syncAllProviderLimits()`'s OAuth and non-OAuth
|
|
* paths.
|
|
*/
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { syncInChunksWithSpacing } from "../../src/lib/usage/providerLimits/chunkedSpacingSync.ts";
|
|
|
|
test("waits between chunks but not after the last chunk when spacingMs > 0", async () => {
|
|
const items = [1, 2, 3, 4];
|
|
const chunkStarts: number[] = [];
|
|
|
|
const start = Date.now();
|
|
await syncInChunksWithSpacing(
|
|
items,
|
|
2,
|
|
40,
|
|
async (item) => {
|
|
chunkStarts.push(Date.now() - start);
|
|
return item;
|
|
},
|
|
() => {}
|
|
);
|
|
|
|
// 2 chunks of 2 → chunkStarts has 4 entries (2 per chunk, same start time).
|
|
assert.equal(chunkStarts.length, 4);
|
|
const chunk1Start = Math.min(chunkStarts[0], chunkStarts[1]);
|
|
const chunk2Start = Math.min(chunkStarts[2], chunkStarts[3]);
|
|
assert.ok(
|
|
chunk2Start - chunk1Start >= 35,
|
|
`expected >=35ms gap between chunks, got ${chunk2Start - chunk1Start}`
|
|
);
|
|
});
|
|
|
|
test("never waits when spacingMs === 0 (opt-out, preserves fast path)", async () => {
|
|
const items = [1, 2, 3, 4];
|
|
const start = Date.now();
|
|
|
|
await syncInChunksWithSpacing(items, 2, 0, async (item) => item, () => {});
|
|
|
|
const elapsed = Date.now() - start;
|
|
assert.ok(elapsed < 30, `expected near-instant run with spacingMs=0, took ${elapsed}ms`);
|
|
});
|
|
|
|
test("chunkSize=1 processes items strictly one at a time (reproduces OAuth semantics)", async () => {
|
|
const items = ["a", "b", "c"];
|
|
const chunks: string[][] = [];
|
|
|
|
await syncInChunksWithSpacing(
|
|
items,
|
|
1,
|
|
0,
|
|
async (item) => item,
|
|
(chunk) => chunks.push([...chunk])
|
|
);
|
|
|
|
assert.deepEqual(chunks, [["a"], ["b"], ["c"]]);
|
|
});
|
|
|
|
test("preserves in-chunk concurrency — all items in a chunk start before any resolves", async () => {
|
|
const items = [1, 2, 3];
|
|
let inFlight = 0;
|
|
let maxInFlight = 0;
|
|
|
|
await syncInChunksWithSpacing(
|
|
items,
|
|
3,
|
|
0,
|
|
async (item) => {
|
|
inFlight++;
|
|
maxInFlight = Math.max(maxInFlight, inFlight);
|
|
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
inFlight--;
|
|
return item;
|
|
},
|
|
() => {}
|
|
);
|
|
|
|
assert.equal(maxInFlight, 3, "all 3 items in the single chunk should overlap");
|
|
});
|
|
|
|
test("delivers chunk + results to onChunkResults, including rejections", async () => {
|
|
const items = [1, 2, 3];
|
|
const seen: Array<{ chunk: number[]; statuses: string[] }> = [];
|
|
|
|
await syncInChunksWithSpacing(
|
|
items,
|
|
2,
|
|
0,
|
|
async (item) => {
|
|
if (item === 2) throw new Error("boom");
|
|
return item * 10;
|
|
},
|
|
(chunk, results) => {
|
|
seen.push({ chunk: [...chunk], statuses: results.map((r) => r.status) });
|
|
}
|
|
);
|
|
|
|
assert.equal(seen.length, 2);
|
|
assert.deepEqual(seen[0].chunk, [1, 2]);
|
|
assert.deepEqual(seen[0].statuses, ["fulfilled", "rejected"]);
|
|
assert.deepEqual(seen[1].chunk, [3]);
|
|
assert.deepEqual(seen[1].statuses, ["fulfilled"]);
|
|
});
|