Files
rea/src/application/JsonFiles.ts
T
gensokyo-dev 0583fc69be perf(javascript): query selected source-to-bundle facts (#6128)
Select completed source-to-bundle mappings and candidates through the shared view owner, preserve reference-file provenance, and retain full Evidence. Reuse bounded JSON reading, heap admission, and cancellation before session writes.

Verified public Redux Toolkit source/map facts with an independent oracle, equivalent CLI/MCP workflows, focused negative controls, and complete CI/review. Historical paired SDK context estimates fall about 64%; timing/resource tradeoffs and final verification receipts are recorded without a general speedup or actual model-token claim.

Fixes #6112.
2026-10-21 18:45:50 +00:00

479 lines
14 KiB
TypeScript

import {
link,
lstat,
mkdtemp,
open,
realpath,
rename,
type FileHandle,
} from "node:fs/promises";
import { basename, dirname, resolve } from "node:path";
import {
EvidenceFileError,
type PublishedEvidenceFile,
} from "../domain/evidenceErrors.js";
import {
AnalysisCancelledError,
AnalysisResourceConstraintError,
} from "../domain/analysisErrorCore.js";
import { err, ok, type Result } from "../domain/result.js";
import {
JsonInputPhysicalReadFailure,
JsonInputCancellationFailure,
readJsonInputFile,
readJsonObjectFile,
type JsonObjectMemberReader,
} from "./JsonInputFile.js";
import { NonRegularFileReadError } from "../filesystem/RegularFile.js";
import { RegularFileCleanupFailure } from "./RegularFileRead.js";
import type { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js";
import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js";
import { bindArtifactFileCleanup } from "../artifacts/ArtifactFileOperation.js";
import {
type AnalysisCleanupLease,
AnalysisCleanupLeaseGroup,
} from "../artifacts/AnalysisCleanupLease.js";
import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js";
import { OwnedStagedOutput } from "../filesystem/OwnedStagedOutput.js";
import { absoluteCallerPath } from "../filesystem/callerPath.js";
/** Request control and its owning operation for an interruptible atomic write. */
export interface TextWriteCancellation {
readonly signal: AbortSignal;
readonly operation: string;
}
type TextWriteResult<Failure = EvidenceFileError | AnalysisCancelledError> =
Result<{ readonly path: string; readonly bytes: number }, Failure>;
/** Read JSON data without changing the caller's existing data-only contract. */
export const readJsonFile = async (
path: string,
signal?: AbortSignal,
resources?: ArtifactResourceScope,
): Promise<
Result<
unknown,
EvidenceFileError | AnalysisResourceConstraintError | AnalysisCancelledError
>
> => {
const read = await readJsonFileWithSource(path, signal, resources);
return read.ok ? ok(read.value.data) : read;
};
/** Read data and the absolute selected path at the same owning regular-file boundary. */
export const readJsonFileWithSource = (
path: string,
signal?: AbortSignal,
resources?: ArtifactResourceScope,
): Promise<
Result<
{ readonly data: unknown; readonly path: string },
EvidenceFileError | AnalysisResourceConstraintError | AnalysisCancelledError
>
> =>
readJsonFileInput(
path,
async (selected) => {
const read = await readJsonInputFile(
selected,
"read_evidence_file",
signal,
resources,
);
return read.ok ? ok({ data: read.value, path: selected }) : read;
},
signal,
);
/** Read selected JSON members through the same regular-file error boundary. */
export const readJsonObjectMembersFile = (
path: string,
scans: readonly ReadonlyMap<string, JsonObjectMemberReader>[],
signal?: AbortSignal,
resources?: ArtifactResourceScope,
): Promise<
Result<
void,
EvidenceFileError | AnalysisResourceConstraintError | AnalysisCancelledError
>
> =>
readJsonFileInput(
path,
(selected) =>
readJsonObjectFile(
selected,
"read_evidence_file",
scans,
signal,
resources,
),
signal,
);
const readJsonFileInput = async <Value>(
path: string,
read: (
selected: string,
) => Promise<
Result<
Value,
| import("../domain/analysisErrorCore.js").AnalysisInputError
| AnalysisResourceConstraintError
>
>,
signal?: AbortSignal,
): Promise<
Result<
Value,
EvidenceFileError | AnalysisResourceConstraintError | AnalysisCancelledError
>
> => {
const requestedPath = absoluteCallerPath(path);
try {
const decoded = await read(requestedPath);
if (!decoded.ok) {
if (decoded.error instanceof AnalysisResourceConstraintError)
return err(decoded.error);
return err(
new EvidenceFileError("read", "invalid-json", {
cause:
decoded.error.cause ??
new SyntaxError(
decoded.error.issues[0]?.message ?? decoded.error.message,
),
path: requestedPath,
}),
);
}
return ok(decoded.value);
} catch (cause: unknown) {
if (cause instanceof RegularFileCleanupFailure) throw cause;
if (cause instanceof AnalysisResourceConstraintError) return err(cause);
if (cause instanceof JsonInputCancellationFailure)
return err(
new AnalysisCancelledError("read_evidence_file", {
cause: cause.reason,
}),
);
if (cause instanceof JsonInputPhysicalReadFailure)
return err(
new EvidenceFileError("read", "io", {
cause: cause.physicalCause,
path: requestedPath,
}),
);
if (isJsonReadCancellation(cause, signal))
return err(
new AnalysisCancelledError("read_evidence_file", {
cause: signal?.reason,
}),
);
return err(
new EvidenceFileError(
"read",
cause instanceof NonRegularFileReadError
? "not-file"
: missingOrIo(cause),
{
cause,
path: requestedPath,
},
),
);
}
};
const isJsonReadCancellation = (
cause: unknown,
signal?: AbortSignal,
): boolean => {
if (signal?.aborted !== true) return false;
if (cause === signal.reason) return true;
return (
cause instanceof Error &&
cause.name === "AbortError" &&
"code" in cause &&
cause.code === "ABORT_ERR" &&
cause.cause === signal.reason
);
};
/** Atomically write text to the caller-supplied path. */
export const writeTextFile = async (
encoded: string,
path: string,
overwrite: boolean,
resources: ArtifactResourceScope,
): Promise<TextWriteResult<EvidenceFileError>> =>
writeTextParts([encoded], path, overwrite, resources);
/** Publish streamed text atomically unless cancellation wins before publication. */
export function writeTextParts(
parts: Iterable<string>,
path: string,
overwrite: boolean,
resources: ArtifactResourceScope,
): Promise<TextWriteResult<EvidenceFileError>>;
export function writeTextParts(
parts: Iterable<string>,
path: string,
overwrite: boolean,
resources: ArtifactResourceScope,
cancellation: TextWriteCancellation | undefined,
): Promise<TextWriteResult>;
export function writeTextParts(
parts: Iterable<string>,
path: string,
overwrite: boolean,
resources: ArtifactResourceScope,
cancellation?: TextWriteCancellation,
): Promise<TextWriteResult> {
return resources
.run(() =>
writeTextPartsOwned(parts, path, overwrite, resources, cancellation),
)
.catch((cause: unknown) => {
const cleanup =
cause instanceof ArtifactReaderFailure && cause.cleanup !== undefined
? cause.cleanup
: undefined;
const error = new EvidenceFileError("write", "io", {
cause,
path: absoluteCallerPath(path),
...(cleanup === undefined ? {} : { cleanup }),
});
// A failed admission retry names its exact retained leases.
bindArtifactFileCleanup(cause, error);
return err(error);
});
}
const writeTextPartsOwned = async (
parts: Iterable<string>,
path: string,
overwrite: boolean,
resources: ArtifactResourceScope,
cancellation?: TextWriteCancellation,
): Promise<TextWriteResult> => {
const requestedPath = absoluteCallerPath(path);
try {
assertWriteActive(cancellation);
if (process.platform !== "win32" && requestedPath.endsWith("/"))
return err(
new EvidenceFileError("write", "not-file", { path: requestedPath }),
);
const canonicalParent = await realpath(dirname(requestedPath));
const destination = resolve(canonicalParent, basename(requestedPath));
const existing = await lstat(destination).catch((cause: unknown) => {
if (fileErrorCode(cause) === "ENOENT") return undefined;
throw cause;
});
if (existing !== undefined) {
if (!overwrite)
return err(
new EvidenceFileError("write", "exists", { path: requestedPath }),
);
if (!existing.isFile() || existing.isSymbolicLink())
return err(
new EvidenceFileError("write", "not-file", { path: requestedPath }),
);
}
assertWriteActive(cancellation);
const bytes = await publishFile(
destination,
parts,
overwrite,
resources,
cancellation,
);
return ok({ path: requestedPath, bytes });
} catch (cause: unknown) {
if (cause instanceof StagedOutputCleanupFailure) {
const cleanup = {
reason: failureMessage(cause.cleanupCause),
resources: [cause.owner.directory],
};
if (cause.outcome.ok)
return stagedCleanupFailure(
new EvidenceFileError("write", "io", {
cause,
path: requestedPath,
cleanup,
published: { ...cause.outcome.value, path: requestedPath },
}),
cause.lease,
);
if (cause.outcome.error instanceof AnalysisCancelledError)
return stagedCleanupFailure(
new AnalysisCancelledError(cause.outcome.error.operation, {
cause: cause.outcome.error.cause,
cleanupPrimary: cause.outcome.error,
cleanup,
}),
cause.lease,
);
return stagedCleanupFailure(
new EvidenceFileError("write", missingOrIo(cause.outcome.error), {
cause,
path: requestedPath,
cleanup,
}),
cause.lease,
);
}
if (
cancellation?.signal.aborted === true &&
cause instanceof AnalysisCancelledError &&
cause.operation === cancellation.operation
)
return err(cause);
if (!overwrite && fileErrorCode(cause) === "EEXIST")
return err(
new EvidenceFileError("write", "exists", {
cause,
path: requestedPath,
}),
);
return err(
new EvidenceFileError("write", missingOrIo(cause), {
cause,
path: requestedPath,
}),
);
}
};
/** The retained staging lease clears this error only when a retry confirms release. */
const stagedCleanupFailure = <
Failure extends EvidenceFileError | AnalysisCancelledError,
>(
error: Failure,
lease: AnalysisCleanupLease,
): Result<never, Failure> => {
new AnalysisCleanupLeaseGroup(error, [lease]);
return err(error);
};
/** A missing path or parent is a selection error, not a permission failure. */
const missingOrIo = (cause: unknown): "missing" | "io" => {
const code = fileErrorCode(cause);
return code === "ENOENT" || code === "ENOTDIR" ? "missing" : "io";
};
const publishFile = async (
destination: string,
parts: Iterable<string>,
overwrite: boolean,
resources: ArtifactResourceScope,
cancellation?: TextWriteCancellation,
): Promise<number> => {
const stagingDirectory = await mkdtemp(
resolve(dirname(destination), ".rea-write-"),
);
const owner = await OwnedStagedOutput.create(stagingDirectory);
let outcome: Result<PublishedEvidenceFile, unknown>;
const staged = resolve(stagingDirectory, "content");
try {
const file = await open(staged, "wx", 0o600);
owner.setFile(new OwnedFileHandle(file));
let written: Result<number, unknown>;
try {
const bytes = await writeStagedParts(file, parts, cancellation);
assertWriteActive(cancellation);
await file.sync();
written = ok(bytes);
} catch (cause: unknown) {
written = err(cause);
}
try {
await owner.closeFile();
} catch (cause: unknown) {
if (written.ok) written = err(cause);
}
if (!written.ok) throw written.error;
// Once submitted, atomic publication can win a later cancellation race.
assertWriteActive(cancellation);
await owner.assertReadyForPublication(staged);
assertWriteActive(cancellation);
if (overwrite) {
await rename(staged, destination);
owner.recordPublishedRename();
}
// A hard link publishes complete bytes atomically and cannot replace an existing name.
else await link(staged, destination);
outcome = ok({ path: destination, bytes: written.value });
} catch (cause: unknown) {
outcome = err(cause);
}
// One cleanup phase owns both the open descriptor (if any) and its staging directory.
const released = await resources.release({
kind: "staged-output",
resource: owner.directory,
output: owner,
});
if (released.kind === "failed")
throw new StagedOutputCleanupFailure(
outcome,
released.cause,
owner,
released.lease,
);
if (!outcome.ok) throw outcome.error;
return outcome.value.bytes;
};
class StagedOutputCleanupFailure extends Error {
constructor(
readonly outcome: Result<PublishedEvidenceFile, unknown>,
readonly cleanupCause: unknown,
readonly owner: OwnedStagedOutput,
readonly lease: AnalysisCleanupLease,
) {
super("Staged output cleanup failed", {
cause: outcome.ok ? cleanupCause : outcome.error,
});
}
}
const failureMessage = (cause: unknown): string =>
cause instanceof Error ? cause.message || cause.name : String(cause);
const writeStagedParts = async (
file: FileHandle,
parts: Iterable<string>,
cancellation?: TextWriteCancellation,
): Promise<number> => {
assertWriteActive(cancellation);
const iterator = parts[Symbol.iterator]();
let exhausted = false;
let bytes = 0;
try {
for (;;) {
assertWriteActive(cancellation);
const part = iterator.next();
if (part.done) exhausted = true;
assertWriteActive(cancellation);
if (part.done) return bytes;
await file.writeFile(part.value, { encoding: "utf8" });
bytes += Buffer.byteLength(part.value, "utf8");
}
} finally {
if (!exhausted) iterator.return?.();
}
};
const assertWriteActive = (cancellation?: TextWriteCancellation): void => {
if (cancellation?.signal.aborted === true)
throw new AnalysisCancelledError(cancellation.operation, {
cause: cancellation.signal.reason,
});
};
const fileErrorCode = (cause: unknown): unknown =>
typeof cause === "object" && cause !== null && "code" in cause
? cause.code
: undefined;