Files
workinf_Blender_Wasm/tools/web/server-job-fault.mjs
mes123456 380cbed4ff
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions
Checkpoint web parity through Chromium input tasks
2026-08-19 10:39:03 -04:00

71 lines
3.4 KiB
JavaScript

export const SERVER_JOB_FAULT_SCHEMA = 1;
export const SERVER_JOB_FAULT_CODES = Object.freeze({
SUCCEEDED: "SERVER_JOB_SUCCEEDED",
CANCELLED: "SERVER_JOB_CANCELLED",
TIMEOUT: "SERVER_JOB_TIMEOUT",
OOM: "SERVER_JOB_OOM",
SIGNAL: "SERVER_JOB_SIGNAL",
EXIT_FAILED: "SERVER_JOB_EXIT_FAILED",
});
function invalid(message) {
throw new Error(`SERVER_JOB_FAULT_INVALID: ${message}`);
}
function revision(value, field) {
if (!Number.isSafeInteger(value) || value < 0) invalid(`${field} must be a non-negative revision`);
return value;
}
function optionalBoolean(value, field) {
if (value !== undefined && typeof value !== "boolean") invalid(`${field} must be boolean`);
return value === true;
}
export function classifyServerJobFault(value) {
if (!value || typeof value !== "object") invalid("input is invalid");
const cancelRequested = optionalBoolean(value.cancelRequested, "cancelRequested");
const timedOut = optionalBoolean(value.timedOut, "timedOut");
const oom = optionalBoolean(value.oom, "oom");
const memoryLimitBytes = value.memoryLimitBytes === undefined ? null : revision(value.memoryLimitBytes, "memoryLimitBytes");
const memoryBytes = value.memoryBytes === undefined ? null : revision(value.memoryBytes, "memoryBytes");
const memoryExceeded = oom || (memoryLimitBytes !== null && memoryBytes !== null && memoryBytes > memoryLimitBytes);
const signal = value.signal === null || value.signal === undefined ? null : String(value.signal);
const exitCode = value.code === null || value.code === undefined ? null : value.code;
if (exitCode !== null && (!Number.isInteger(exitCode) || exitCode < 0)) invalid("code must be a non-negative integer");
let code = SERVER_JOB_FAULT_CODES.SUCCEEDED;
let state = "SUCCEEDED";
if (cancelRequested || value.status === "CANCELLED") { code = SERVER_JOB_FAULT_CODES.CANCELLED; state = "CANCELLED"; }
else if (timedOut) { code = SERVER_JOB_FAULT_CODES.TIMEOUT; state = "FAILED"; }
else if (memoryExceeded) { code = SERVER_JOB_FAULT_CODES.OOM; state = "FAILED"; }
else if (signal) { code = SERVER_JOB_FAULT_CODES.SIGNAL; state = "FAILED"; }
else if (exitCode !== null && exitCode !== 0) { code = SERVER_JOB_FAULT_CODES.EXIT_FAILED; state = "FAILED"; }
return Object.freeze({ schemaVersion: SERVER_JOB_FAULT_SCHEMA, state, code, exitCode, signal, timedOut, memoryExceeded, publish: state === "SUCCEEDED", revisionPreserved: state !== "SUCCEEDED" });
}
export function createServerJobFaultReceipt(value) {
if (!value || typeof value !== "object") invalid("receipt input is invalid");
const baseRevision = revision(value.baseRevision, "baseRevision");
const currentRevision = revision(value.currentRevision, "currentRevision");
const classification = classifyServerJobFault(value);
if (classification.state !== "SUCCEEDED" && currentRevision !== baseRevision) {
throw new Error("SERVER_JOB_REVISION_CONFLICT: failed job cannot replace a newer project revision");
}
return Object.freeze({
schemaVersion: SERVER_JOB_FAULT_SCHEMA,
state: classification.state,
code: classification.code,
stage: "PROCESS",
exitCode: classification.exitCode,
signal: classification.signal,
timedOut: classification.timedOut,
memoryExceeded: classification.memoryExceeded,
baseRevision,
currentRevision,
committedRevision: currentRevision,
publish: classification.publish,
revisionPreserved: classification.revisionPreserved,
execution: "DISABLED",
});
}