UNPKG

lsh-framework

Version:

A powerful, extensible shell with advanced job management, database persistence, and modern CLI features

157 lines (156 loc) 5.58 kB
/** * Database Job Storage * Persistent storage for jobs and executions using DatabasePersistence * Used by CronJobManager and other database-backed managers */ import DatabasePersistence from './database-persistence.js'; export class DatabaseJobStorage { persistence; userId; constructor(userId) { this.userId = userId; this.persistence = new DatabasePersistence(userId); } async save(job) { // Map BaseJobSpec to database format const dbJob = { job_id: job.id, command: job.command, started_at: job.startedAt?.toISOString(), completed_at: job.completedAt?.toISOString(), status: job.status, exit_code: job.exitCode, output: job.stdout, error: job.stderr, }; // Save using available method await this.persistence.saveJob(dbJob); } async get(_jobId) { // This would require adding a method to DatabasePersistence // For now, return null and rely on list() filtering return null; } async list(_filter) { // Get active jobs from database const dbJobs = await this.persistence.getActiveJobs(); // Convert to BaseJobSpec format const jobs = dbJobs.map(dbJob => ({ id: dbJob.job_id, name: dbJob.job_id, // Using job_id as name since name field doesn't exist command: dbJob.command, status: this.mapDbStatusToJobStatus(dbJob.status), createdAt: new Date(dbJob.started_at), startedAt: new Date(dbJob.started_at), completedAt: dbJob.completed_at ? new Date(dbJob.completed_at) : undefined, user: this.userId, tags: [], priority: 5, maxRetries: 3, retryCount: 0, databaseSync: true, exitCode: dbJob.exit_code, stdout: dbJob.output, stderr: dbJob.error, })); return jobs; } mapDbStatusToJobStatus(dbStatus) { switch (dbStatus) { case 'running': return 'running'; case 'completed': case 'success': return 'completed'; case 'stopped': return 'stopped'; case 'paused': return 'paused'; case 'failed': case 'timeout': return 'failed'; case 'killed': return 'killed'; default: return 'created'; } } async update(jobId, updates) { // Update by saving again (upsert behavior) if (updates.command) { const dbJob = { job_id: jobId, command: updates.command, started_at: updates.startedAt?.toISOString(), completed_at: updates.completedAt?.toISOString(), status: updates.status || 'running', exit_code: updates.exitCode, output: updates.stdout, error: updates.stderr, }; await this.persistence.saveJob(dbJob); } } async delete(jobId) { // DatabasePersistence doesn't have a delete method yet // This would need to be added console.warn(`Delete not implemented for job ${jobId}`); } async saveExecution(execution) { // Map to database format and save as job const dbJob = { job_id: execution.jobId, command: execution.command, started_at: execution.startTime.toISOString(), completed_at: execution.endTime?.toISOString(), status: execution.status, exit_code: execution.exitCode, output: execution.stdout, error: execution.stderr || execution.errorMessage, }; await this.persistence.saveJob(dbJob); } async getExecutions(jobId, limit = 50) { // Get active jobs (no specific history method available yet) const dbJobs = await this.persistence.getActiveJobs(); const jobExecutions = dbJobs.filter(job => job.job_id === jobId); return jobExecutions.slice(0, limit).map(dbExec => ({ executionId: `exec_${dbExec.job_id}_${Date.now()}`, jobId: dbExec.job_id, jobName: dbExec.job_id, command: dbExec.command, startTime: new Date(dbExec.started_at), endTime: dbExec.completed_at ? new Date(dbExec.completed_at) : undefined, duration: dbExec.completed_at ? new Date(dbExec.completed_at).getTime() - new Date(dbExec.started_at).getTime() : undefined, status: this.mapDbStatus(dbExec.status), exitCode: dbExec.exit_code, stdout: dbExec.output, stderr: dbExec.error, errorMessage: dbExec.error, })); } mapDbStatus(dbStatus) { switch (dbStatus) { case 'running': return 'running'; case 'completed': case 'success': return 'completed'; case 'failed': return 'failed'; case 'killed': return 'killed'; case 'timeout': return 'timeout'; default: return 'failed'; } } async cleanup() { // DatabasePersistence maintains its own connections // No cleanup needed here } } export default DatabaseJobStorage;