UNPKG

@backgroundjs/core

Version:

An extendible background job queue for js/ts applications

133 lines (118 loc) 3.58 kB
import { Job, JobStatus } from "../types"; import { JobStorage } from "./base-storage"; export class InMemoryJobStorage implements JobStorage { private jobs: Map<string, Job> = new Map(); private logging: boolean = false; constructor(options?: { logging?: boolean }) { this.logging = options?.logging || false; } async saveJob(job: Job): Promise<void> { try { this.jobs.set(job.id, job); } catch (error) { if (this.logging) { console.error(`[InMemoryJobStorage] Error saving job:`, error); } } } async getJob(id: string): Promise<Job | null> { try { return this.jobs.get(id) || null; } catch (error) { if (this.logging) { console.error(`[InMemoryJobStorage] Error getting job:`, error); } return null; } } async getJobsByStatus(status: JobStatus): Promise<Job[]> { try { return Array.from(this.jobs.values()).filter( (job) => job.status === status, ); } catch (error) { if (this.logging) { console.error( `[InMemoryJobStorage] Error getting jobs by status:`, error, ); } return []; } } async updateJob(job: Job): Promise<void> { try { if (!this.jobs.has(job.id)) { throw new Error(`Job with id ${job.id} not found`); } this.jobs.set(job.id, job); } catch (error) { if (this.logging) { console.error(`[InMemoryJobStorage] Error updating job:`, error); } } } async acquireNextJob(): Promise<Job | null> { try { // First, filter to get eligible jobs const pendingJobs = Array.from(this.jobs.values()).filter((job) => { if (job.status !== "pending") return false; if (job.scheduledAt) { const now = new Date(); return job.scheduledAt <= now; } return true; }); const sortedJobs = pendingJobs.sort((a, b) => { const priorityA = a.priority || 10; const priorityB = b.priority || 10; if (priorityA !== priorityB) { return priorityA - priorityB; } return a.createdAt.getTime() - b.createdAt.getTime(); }); const job = sortedJobs[0]; if (!job) return null; job.status = "processing"; job.startedAt = new Date(); // Store the updated job this.jobs.set(job.id, job); return job; } catch (error) { if (this.logging) { console.error(`[InMemoryJobStorage] Error acquiring next job:`, error); } return null; } } async completeJob(jobId: string, result: any): Promise<void> { try { const job = await this.getJob(jobId); if (!job) { throw new Error(`Job with id ${jobId} not found`); } job.status = "completed"; job.result = result; await this.updateJob(job); } catch (error) { if (this.logging) { console.error(`[InMemoryJobStorage] Error completing job:`, error); } } } async failJob(jobId: string, error: string): Promise<void> { try { const job = await this.getJob(jobId); if (!job) { throw new Error(`Job with id ${jobId} not found`); } job.status = "failed"; job.error = error; await this.updateJob(job); } catch (error) { if (this.logging) { console.error(`[InMemoryJobStorage] Error failing job:`, error); } } } }