perf(application): scan version artifacts in parallel

This commit is contained in:
N0zoM1z0 2026-07-14 19:23:00 +08:00
parent 2d1e021782
commit c00739bb1f
2 changed files with 149 additions and 14 deletions

View File

@ -34,6 +34,43 @@ export interface InventoryEvidencePages {
readonly right: readonly Evidence[];
}
/** Injectable artifact scan boundary used by paired version inventory. */
export type VersionInventoryScanner = typeof scanAuthorizedArtifactInventory;
/** Inputs shared by the two scans in one version comparison. */
export interface VersionInventoryScanOptions {
readonly leftPath: string;
readonly rightPath: string;
readonly inputRoots: readonly string[];
readonly limits: ArtifactLimits;
readonly signal?: AbortSignal;
readonly integrity: ArtifactIntegrityPolicy;
}
/** Start both independent version scans while preserving left/right identity. */
export const scanVersionInventories = async (
options: VersionInventoryScanOptions,
scanner: VersionInventoryScanner = scanAuthorizedArtifactInventory,
): Promise<VersionSnapshots> => {
const [left, right] = await Promise.all([
scanner(
options.leftPath,
options.inputRoots,
options.limits,
options.signal,
options.integrity,
),
scanner(
options.rightPath,
options.inputRoots,
options.limits,
options.signal,
options.integrity,
),
]);
return { left, right };
};
/** Authorize and scan both inputs once under the same bounded traversal policy. */
export const scanVersions = async (
input: CrossVersionInvestigationInput,
@ -51,21 +88,16 @@ export const scanVersions = async (
enabled: integrityContinueEnabled,
maxMismatches: input.max_integrity_mismatches,
};
const left = await scanAuthorizedArtifactInventory(
input.left_path,
inputRoots,
limits,
signal,
integrity,
return ok(
await scanVersionInventories({
leftPath: input.left_path,
rightPath: input.right_path,
inputRoots,
limits,
...(signal === undefined ? {} : { signal }),
integrity,
}),
);
const right = await scanAuthorizedArtifactInventory(
input.right_path,
inputRoots,
limits,
signal,
integrity,
);
return ok({ left, right });
} catch (cause: unknown) {
if (cause instanceof ArtifactReaderFailure)
return err(

View File

@ -0,0 +1,103 @@
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { scanArtifactInventory } from "../src/application/ArtifactInventory.js";
import {
scanVersionInventories,
type VersionInventoryScanner,
} from "../src/application/CrossVersionInventory.js";
const LIMITS = {
maxEntries: 10,
maxTotalBytes: 1_024,
maxEntryBytes: 512,
maxCompressionRatio: 10,
maxDepth: 8,
maxPathBytes: 256,
} as const;
const INTEGRITY = {
mode: "fail",
approved: false,
enabled: false,
maxMismatches: 1,
} as const;
const deferred = <Value>() => {
let resolvePromise: (value: Value) => void = () => undefined;
let rejectPromise: (reason: unknown) => void = () => undefined;
const promise = new Promise<Value>((resolve, reject) => {
resolvePromise = resolve;
rejectPromise = reject;
});
return { promise, resolve: resolvePromise, reject: rejectPromise };
};
describe("cross-version inventory", () => {
it("starts both scans together and preserves left/right result order", async () => {
const root = await mkdtemp(join(tmpdir(), "rea-version-inventory-"));
try {
const artifact = join(root, "artifact.js");
await writeFile(artifact, "export const value = 1;\n");
const snapshot = await scanArtifactInventory(artifact, LIMITS);
const left = deferred<typeof snapshot>();
const right = deferred<typeof snapshot>();
const calls: string[] = [];
const controller = new AbortController();
const scanner: VersionInventoryScanner = (...arguments_) => {
const [path, roots, limits, signal, integrity] = arguments_;
calls.push(path);
expect(roots).toEqual([root]);
expect(limits).toBe(LIMITS);
expect(signal).toBe(controller.signal);
expect(integrity).toBe(INTEGRITY);
return path === "left" ? left.promise : right.promise;
};
const result = scanVersionInventories(
{
leftPath: "left",
rightPath: "right",
inputRoots: [root],
limits: LIMITS,
signal: controller.signal,
integrity: INTEGRITY,
},
scanner,
);
expect(calls).toEqual(["left", "right"]);
right.resolve(snapshot);
left.resolve(snapshot);
await expect(result).resolves.toEqual({
left: snapshot,
right: snapshot,
});
} finally {
await rm(root, { recursive: true, force: true });
}
});
it("rejects promptly when either parallel scan fails", async () => {
const left = deferred<never>();
const failure = new Error("right scan failed");
const scanner: VersionInventoryScanner = (path) =>
path === "left" ? left.promise : Promise.reject(failure);
await expect(
scanVersionInventories(
{
leftPath: "left",
rightPath: "right",
inputRoots: ["/approved"],
limits: LIMITS,
integrity: INTEGRITY,
},
scanner,
),
).rejects.toBe(failure);
});
});