feat: complete TASK-WP3-04 worker recovery

This commit is contained in:
suyx
2026-08-03 03:31:01 +08:00
parent 0fb0d088a7
commit 433ccdcf86
6 changed files with 387 additions and 15 deletions
+13
View File
@@ -260,6 +260,8 @@ export class GenerationSubmissionService {
const prompt = normalizePrompt(input.prompt);
const model = this.models.readModel(input.modelId);
if (!model) throw new GenerationSubmissionError("generation_blocked", { errorCategory: "model_disabled" });
const workerState = this.database.prepare("SELECT status FROM worker_runtime_state WHERE singleton = 1").get() as { status: "ready" | "degraded" } | undefined;
if (workerState?.status === "degraded") throw new GenerationSubmissionError("generation_blocked", { errorCategory: "gateway_contract_invalid" });
if (model.configVersion !== input.modelConfigVersion || model.creditCost !== input.confirmedCreditCost) {
throw new GenerationSubmissionError("model_config_stale", {
latest: { configVersion: model.configVersion, creditCost: model.creditCost, modelId: model.modelId },
@@ -501,6 +503,14 @@ export class GenerationSubmissionService {
this.ensureColumn("generation_jobs", "submission_ready", "INTEGER NOT NULL DEFAULT 0");
this.ensureColumn("generation_jobs", "config_snapshot_json", "TEXT");
this.database.exec(`
CREATE TABLE IF NOT EXISTS worker_runtime_state (
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
status TEXT NOT NULL CHECK (status IN ('ready', 'degraded')),
reason TEXT,
owner_id TEXT,
lock_expires_at INTEGER,
updated_at INTEGER NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS generation_jobs_active_owner
ON generation_jobs(owner_id) WHERE status IN ('queued', 'running');
CREATE UNIQUE INDEX IF NOT EXISTS generation_jobs_client_submission
@@ -530,5 +540,8 @@ export class GenerationSubmissionService {
WHEN dada_allow_privacy_purge() <> 1
BEGIN SELECT RAISE(ABORT, 'generation_reference_snapshot_immutable'); END;
`);
this.ensureColumn("worker_runtime_state", "owner_id", "TEXT");
this.ensureColumn("worker_runtime_state", "lock_expires_at", "INTEGER");
this.database.prepare("INSERT OR IGNORE INTO worker_runtime_state (singleton, status, reason, owner_id, lock_expires_at, updated_at) VALUES (1, 'ready', NULL, NULL, NULL, ?)").run(this.clock());
}
}