fix: 持久化 runner 空闲保活策略
This commit is contained in:
@@ -44,6 +44,7 @@ export interface RunnerJobDefaults {
|
||||
envIdentity?: string;
|
||||
artifactCatalogFile?: string;
|
||||
serviceAccountName?: string;
|
||||
runnerIdleTimeoutMs?: number;
|
||||
kubectlCommand?: string;
|
||||
unideskSshEndpointEnv?: JsonRecord;
|
||||
}
|
||||
@@ -57,6 +58,7 @@ export interface CreateRunnerJobInput extends JsonRecord {
|
||||
runnerId?: string;
|
||||
sourceCommit?: string;
|
||||
serviceAccountName?: string;
|
||||
runnerIdleTimeoutMs?: number;
|
||||
idempotencyKey?: string;
|
||||
imageRef?: JsonRecord;
|
||||
transientEnv?: JsonRecord[];
|
||||
@@ -85,6 +87,7 @@ export async function createKubernetesRunnerJob(options: { store: AgentRunStore;
|
||||
const transientEnv = assembleToolContextTransientEnv(run.executionPolicy, transientEnvField(options.input.transientEnv), options.defaults);
|
||||
const attemptId = optionalString(options.input.attemptId) ?? `attempt_${Date.now().toString(36)}`;
|
||||
const runnerId = optionalString(options.input.runnerId);
|
||||
const runnerIdleTimeoutMs = optionalPositiveInteger(options.input.runnerIdleTimeoutMs, "runnerIdleTimeoutMs") ?? options.defaults.runnerIdleTimeoutMs;
|
||||
const transientEnvSecretName = transientEnv.length > 0 ? transientEnvSecretNameForRun(run.id, commandId, attemptId) : null;
|
||||
const renderTransientEnv = transientEnvSecretName ? transientEnvWithSecretRefs(transientEnv, transientEnvSecretName) : transientEnv;
|
||||
const normalizedPayload = {
|
||||
@@ -97,6 +100,7 @@ export async function createKubernetesRunnerJob(options: { store: AgentRunStore;
|
||||
serviceAccountName: serviceAccountName ?? null,
|
||||
attemptId: optionalString(options.input.attemptId) ?? null,
|
||||
runnerId: optionalString(options.input.runnerId) ?? null,
|
||||
runnerIdleTimeoutMs: runnerIdleTimeoutMs ?? null,
|
||||
transientEnv: transientEnv.map((item) => ({ name: item.name, valueHash: stableHash(item.value), sensitive: true })),
|
||||
};
|
||||
const payloadHash = stableHash(normalizedPayload);
|
||||
@@ -150,6 +154,7 @@ export async function createKubernetesRunnerJob(options: { store: AgentRunStore;
|
||||
namespace,
|
||||
sourceCommit,
|
||||
transientEnv: renderTransientEnv,
|
||||
...(runnerIdleTimeoutMs !== undefined ? { runnerIdleTimeoutMs } : {}),
|
||||
...(serviceAccountName ? { serviceAccountName } : {}),
|
||||
...(sessionPvc ? { sessionPvc } : {}),
|
||||
};
|
||||
@@ -214,6 +219,7 @@ export async function createKubernetesRunnerJob(options: { store: AgentRunStore;
|
||||
workReady: staticWorkReadyCapabilitySummary(),
|
||||
retention: {
|
||||
ttlSecondsAfterFinished: render.ttlSecondsAfterFinished,
|
||||
runnerIdleTimeoutMs: render.runnerIdleTimeoutMs,
|
||||
},
|
||||
pollActions: [
|
||||
runnerJobActionDescriptor({ action: "inspect-run", operation: "describe", resourceKind: "run", resourceName: run.id, runId: run.id }),
|
||||
@@ -479,6 +485,12 @@ function optionalString(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
function optionalPositiveInteger(value: unknown, key: string): number | undefined {
|
||||
if (value === undefined || value === null) return undefined;
|
||||
if (!Number.isInteger(value) || Number(value) <= 0) throw new AgentRunError("schema-invalid", `${key} must be a positive integer`, { httpStatus: 400 });
|
||||
return Number(value);
|
||||
}
|
||||
|
||||
function objectPath(value: unknown, path: string[]): string | null {
|
||||
let current: unknown = value;
|
||||
for (const key of path) {
|
||||
|
||||
@@ -46,6 +46,7 @@ function runnerJobDefaultsForRequest(defaults: ManagerServerOptions["runnerJobDe
|
||||
...optionalStringRecord("envIdentity", defaults?.envIdentity ?? process.env.AGENTRUN_ENV_IDENTITY),
|
||||
...optionalStringRecord("artifactCatalogFile", defaults?.artifactCatalogFile ?? process.env.AGENTRUN_ARTIFACT_CATALOG_FILE),
|
||||
serviceAccountName: defaults?.serviceAccountName ?? process.env.AGENTRUN_RUNNER_SERVICE_ACCOUNT ?? "agentrun-v01-runner",
|
||||
...(defaults?.runnerIdleTimeoutMs !== undefined ? { runnerIdleTimeoutMs: defaults.runnerIdleTimeoutMs } : optionalPositiveIntegerRecord("runnerIdleTimeoutMs", process.env.AGENTRUN_RUNNER_IDLE_TIMEOUT_MS)),
|
||||
...(defaults?.kubectlCommand ? { kubectlCommand: defaults.kubectlCommand } : {}),
|
||||
...(defaults?.unideskSshEndpointEnv ? { unideskSshEndpointEnv: defaults.unideskSshEndpointEnv } : {}),
|
||||
};
|
||||
@@ -64,6 +65,7 @@ export interface ManagerServerOptions {
|
||||
envIdentity?: string;
|
||||
artifactCatalogFile?: string;
|
||||
serviceAccountName?: string;
|
||||
runnerIdleTimeoutMs?: number;
|
||||
kubectlCommand?: string;
|
||||
unideskSshEndpointEnv?: JsonRecord;
|
||||
};
|
||||
@@ -947,6 +949,13 @@ function optionalStringRecord(key: string, value: unknown): JsonRecord {
|
||||
return typeof value === "string" && value.trim().length > 0 ? { [key]: value.trim() } : {};
|
||||
}
|
||||
|
||||
function optionalPositiveIntegerRecord(key: string, value: unknown): JsonRecord {
|
||||
if (value === undefined || value === null || value === "") return {};
|
||||
const parsed = Number(value);
|
||||
if (!Number.isInteger(parsed) || parsed <= 0) throw new AgentRunError("schema-invalid", `${key} must be a positive integer`, { httpStatus: 400 });
|
||||
return { [key]: parsed };
|
||||
}
|
||||
|
||||
function normalizeError(error: unknown): AgentRunError {
|
||||
if (error instanceof AgentRunError) return error;
|
||||
return new AgentRunError("infra-failed", error instanceof Error ? error.message : String(error), { httpStatus: 500 });
|
||||
|
||||
Reference in New Issue
Block a user