Checkpoint web parity through Chromium input tasks
This commit is contained in:
70
tools/web/server-job-fault.mjs
Normal file
70
tools/web/server-job-fault.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
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",
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user