Reuse checked bootstrap catalogs and coordinate execution deadlines

This commit is contained in:
Timothy J. Aveni
2026-10-09 17:10:14 -07:00
parent 041a9e26ad
commit 2ae7f00acb
4 changed files with 154 additions and 18 deletions
+72 -2
View File
@@ -1,4 +1,4 @@
import { compileInspectionTemplates, type InspectionTemplate } from "./inspection.js";
import { compileInspectionTemplates, type InspectionTemplate, type InspectionKernel } from "./inspection.js";
import path from "node:path";
import { loadCheckedArtifactWorld } from "./receipts.js";
import { contentArtifactUrl, loadArtifactWorld, type LoadedArtifactWorld } from "./files.js";
@@ -45,6 +45,7 @@ export function clientContractCatalog(
plan: ExecutionPlan,
installation: ExecutionInstallation,
requestedPackages: readonly string[],
checkedKernel?: InspectionKernel,
): ClientContractCatalog {
if (installation.plan !== plan.digest || hexDigest(plan.definition) !== plan.digest)
throw new ExecutionPlanError(
@@ -69,7 +70,7 @@ export function clientContractCatalog(
.map((operation) => publicOperationContract(iface, operation)),
),
);
const inspection = compileInspectionTemplates(plan);
const inspection = compileInspectionTemplates(plan, checkedKernel);
return {
inspections: inspection.templates,
resultInterfaces: Object.fromEntries(
@@ -98,6 +99,75 @@ export function clientContractCatalog(
};
}
/** Candidate-owned compiler output, never graph state or authorization. Compile
* once, then project each requested package set without hashing/recompiling the
* plan. Reserve bounded metadata before compilation; disposal releases both the
* catalog and its charge. Callers must supply the candidate's checked inputs. */
export function createClientContractCatalog(
plan: ExecutionPlan,
installation: ExecutionInstallation,
metadata: CandidateMetadataScope,
checkedKernel?: InspectionKernel,
) {
const revisions = plan.definition.workspace.packageImports.map((pkg) => pkg.revisionId);
const installed = new Set<string>(revisions);
let catalog: ClientContractCatalog | undefined;
let release: (() => void) | undefined;
let closed = false;
const freeze = (value: unknown, seen = new WeakSet<object>()) => {
if (!value || typeof value !== "object" || seen.has(value)) return;
seen.add(value);
for (const child of Object.values(value)) freeze(child, seen);
Object.freeze(value);
};
return {
select(requestedPackages: readonly string[]): ClientContractCatalog {
if (closed) throw Error("CANDIDATE_METADATA_CLOSED");
for (const revision of requestedPackages)
if (!installed.has(revision))
throw new ExecutionPlanError("UNINSTALLED_PACKAGE", revision, "Requested catalog package is not installed");
if (!catalog) {
// Like other candidate admission charges, this is an allocation estimate,
// not a V8 heap limit. The process/cgroup ceiling bounds transient work.
const reservation = metadata.reserve(32 * 1024 * 1024);
try {
const compiled = clientContractCatalog(plan, installation, revisions, checkedKernel);
const bytes = Buffer.byteLength(JSON.stringify(compiled));
if (bytes > 8 * 1024 * 1024) throw Error("CANDIDATE_CATALOG_LIMIT");
freeze(compiled);
// No await between reservations: replacing the transient upper bound
// with a smaller retained estimate cannot race another admission.
reservation();
release = metadata.reserve(Math.max(64 * 1024, bytes * 4));
catalog = compiled;
} catch (error) {
reservation();
throw error;
}
}
const requested = new Set(requestedPackages);
return {
inspections: catalog.inspections,
resultInterfaces: catalog.resultInterfaces,
operations: catalog.operations,
queries: [
...catalog.queries.filter((query) => !installed.has(query.package)),
...requestedPackages.flatMap((revision) => catalog!.queries.filter((query) => query.package === revision)),
],
components: catalog.components.filter((component) => requested.has(component.packageRevision)),
moduleBindings: catalog.moduleBindings.filter((binding) => requested.has(binding.packageRevision)),
presentations: catalog.presentations.filter((presentation) => requested.has(presentation.packageRevision)),
};
},
close() {
closed = true;
catalog = undefined;
release?.();
release = undefined;
},
};
}
export interface PackageInstallationSelection {
readonly browser?: { readonly id?: string };
readonly service?: { readonly id?: string };