fix(client): ensure digital employee schema

This commit is contained in:
baiyanyun
2026-06-07 18:39:19 +08:00
parent 6deea42de1
commit 5e76828afe
6 changed files with 196 additions and 164 deletions

View File

@@ -10,9 +10,149 @@ const dbPath = path.join(qimingHome, `${APP_NAME_IDENTIFIER}.db`);
let db: Database.Database | null = null;
const DIGITAL_EMPLOYEE_SCHEMA_SQL = `
CREATE TABLE IF NOT EXISTS digital_plans (
id TEXT PRIMARY KEY,
remote_id TEXT,
title TEXT NOT NULL,
objective TEXT,
status TEXT NOT NULL,
source TEXT NOT NULL DEFAULT 'local',
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_tasks (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
title TEXT NOT NULL,
status TEXT NOT NULL,
assigned_skill_id TEXT,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
FOREIGN KEY(plan_id) REFERENCES digital_plans(id)
);
CREATE TABLE IF NOT EXISTS digital_runs (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
status TEXT NOT NULL,
started_at TEXT,
finished_at TEXT,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
FOREIGN KEY(plan_id) REFERENCES digital_plans(id),
FOREIGN KEY(task_id) REFERENCES digital_tasks(id)
);
CREATE TABLE IF NOT EXISTS digital_events (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
run_id TEXT,
kind TEXT NOT NULL,
message TEXT NOT NULL,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
occurred_at TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY(plan_id) REFERENCES digital_plans(id),
FOREIGN KEY(task_id) REFERENCES digital_tasks(id),
FOREIGN KEY(run_id) REFERENCES digital_runs(id)
);
CREATE TABLE IF NOT EXISTS digital_artifacts (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
run_id TEXT,
kind TEXT NOT NULL,
name TEXT,
uri TEXT,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_approvals (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
run_id TEXT,
title TEXT NOT NULL,
status TEXT NOT NULL,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_sync_outbox (
id TEXT PRIMARY KEY,
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
operation TEXT NOT NULL,
payload TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
attempts INTEGER NOT NULL DEFAULT 0,
last_attempt_at TEXT,
error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_sync_attempts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
outbox_id TEXT NOT NULL,
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
operation TEXT NOT NULL,
attempt_no INTEGER NOT NULL,
status TEXT NOT NULL,
error TEXT,
endpoint TEXT,
started_at TEXT NOT NULL,
finished_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_digital_plans_sync ON digital_plans(sync_status);
CREATE INDEX IF NOT EXISTS idx_digital_tasks_plan ON digital_tasks(plan_id);
CREATE INDEX IF NOT EXISTS idx_digital_runs_task ON digital_runs(task_id);
CREATE INDEX IF NOT EXISTS idx_digital_events_plan ON digital_events(plan_id, occurred_at);
CREATE INDEX IF NOT EXISTS idx_digital_sync_outbox_status ON digital_sync_outbox(status, created_at);
CREATE INDEX IF NOT EXISTS idx_digital_sync_attempts_outbox ON digital_sync_attempts(outbox_id, finished_at);
`;
let digitalEmployeeSchemaEnsured = false;
export function initDatabase(): void {
try {
db = new Database(dbPath);
digitalEmployeeSchemaEnsured = false;
log.info('Database initialized at:', dbPath);
// Create tables
@@ -21,148 +161,27 @@ export function initDatabase(): void {
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_plans (
id TEXT PRIMARY KEY,
remote_id TEXT,
title TEXT NOT NULL,
objective TEXT,
status TEXT NOT NULL,
source TEXT NOT NULL DEFAULT 'local',
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_tasks (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
title TEXT NOT NULL,
status TEXT NOT NULL,
assigned_skill_id TEXT,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
FOREIGN KEY(plan_id) REFERENCES digital_plans(id)
);
CREATE TABLE IF NOT EXISTS digital_runs (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
status TEXT NOT NULL,
started_at TEXT,
finished_at TEXT,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
FOREIGN KEY(plan_id) REFERENCES digital_plans(id),
FOREIGN KEY(task_id) REFERENCES digital_tasks(id)
);
CREATE TABLE IF NOT EXISTS digital_events (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
run_id TEXT,
kind TEXT NOT NULL,
message TEXT NOT NULL,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
occurred_at TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY(plan_id) REFERENCES digital_plans(id),
FOREIGN KEY(task_id) REFERENCES digital_tasks(id),
FOREIGN KEY(run_id) REFERENCES digital_runs(id)
);
CREATE TABLE IF NOT EXISTS digital_artifacts (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
run_id TEXT,
kind TEXT NOT NULL,
name TEXT,
uri TEXT,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_approvals (
id TEXT PRIMARY KEY,
remote_id TEXT,
plan_id TEXT,
task_id TEXT,
run_id TEXT,
title TEXT NOT NULL,
status TEXT NOT NULL,
payload TEXT NOT NULL DEFAULT '{}',
sync_status TEXT NOT NULL DEFAULT 'pending',
last_synced_at TEXT,
sync_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_sync_outbox (
id TEXT PRIMARY KEY,
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
operation TEXT NOT NULL,
payload TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
attempts INTEGER NOT NULL DEFAULT 0,
last_attempt_at TEXT,
error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS digital_sync_attempts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
outbox_id TEXT NOT NULL,
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
operation TEXT NOT NULL,
attempt_no INTEGER NOT NULL,
status TEXT NOT NULL,
error TEXT,
endpoint TEXT,
started_at TEXT NOT NULL,
finished_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_digital_plans_sync ON digital_plans(sync_status);
CREATE INDEX IF NOT EXISTS idx_digital_tasks_plan ON digital_tasks(plan_id);
CREATE INDEX IF NOT EXISTS idx_digital_runs_task ON digital_runs(task_id);
CREATE INDEX IF NOT EXISTS idx_digital_events_plan ON digital_events(plan_id, occurred_at);
CREATE INDEX IF NOT EXISTS idx_digital_sync_outbox_status ON digital_sync_outbox(status, created_at);
CREATE INDEX IF NOT EXISTS idx_digital_sync_attempts_outbox ON digital_sync_attempts(outbox_id, finished_at);
`);
ensureDigitalEmployeeSchema();
log.info('Database tables created');
} catch (error) {
log.error('Database initialization failed:', error);
}
}
export function ensureDigitalEmployeeSchema(): boolean {
if (!db) return false;
if (digitalEmployeeSchemaEnsured) return true;
try {
db.exec(DIGITAL_EMPLOYEE_SCHEMA_SQL);
digitalEmployeeSchemaEnsured = true;
return true;
} catch (error) {
log.error('Digital employee schema initialization failed:', error);
return false;
}
}
export function getDb(): Database.Database | null {
return db;
}
@@ -171,6 +190,7 @@ export function closeDb(): void {
if (db) {
db.close();
db = null;
digitalEmployeeSchemaEnsured = false;
log.info('[App] Database closed');
}
}