fix(client): ensure digital employee schema
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user