export const SERVER_JOB_RESOURCE_BUDGET_SCHEMA = 1; export const SERVER_JOB_RESOURCE_LIMITS = Object.freeze({ cpuMs: 60_000, memoryBytes: 512 * 1024 * 1024, processCount: 1, fileCount: 1_024, wallMs: 300_000, outputBytes: 512 * 1024 * 1024, }); const fields = Object.keys(SERVER_JOB_RESOURCE_LIMITS); function integer(value, field, minimum = 0) { if (!Number.isSafeInteger(value) || value < minimum || value > SERVER_JOB_RESOURCE_LIMITS[field]) throw new Error(`SERVER_JOB_BUDGET_EXCEEDED: ${field} is outside the enforced budget`); return value; } export function parseServerJobResourceBudget(value) { if (!value || value.schemaVersion !== SERVER_JOB_RESOURCE_BUDGET_SCHEMA || typeof value !== "object") throw new Error("SERVER_JOB_BUDGET_INVALID: schema is unsupported"); if (Object.keys(value).some((key) => key !== "schemaVersion" && !fields.includes(key))) throw new Error("SERVER_JOB_BUDGET_INVALID: undeclared budget field"); return Object.freeze({ schemaVersion: SERVER_JOB_RESOURCE_BUDGET_SCHEMA, ...Object.fromEntries(fields.map((field) => [field, integer(value[field], field)])) }); } export function createServerJobResourceReceipt(budgetValue, usageValue, status = "SUCCEEDED") { const budget = parseServerJobResourceBudget(budgetValue); if (!usageValue || typeof usageValue !== "object") throw new Error("SERVER_JOB_BUDGET_INVALID: usage is invalid"); const usage = Object.freeze(Object.fromEntries(fields.map((field) => [field, integer(usageValue[field], field)]))); const exceeded = fields.filter((field) => usage[field] > budget[field]); if (exceeded.length > 0) throw new Error(`SERVER_JOB_BUDGET_EXCEEDED: ${exceeded.join(",")}`); if (!["SUCCEEDED", "FAILED", "CANCELLED"].includes(status)) throw new Error("SERVER_JOB_BUDGET_INVALID: status is unsupported"); return Object.freeze({ schemaVersion: SERVER_JOB_RESOURCE_BUDGET_SCHEMA, status, budget, usage, enforced: true, exceeded: [] }); }