export function createInMemoryImageDerivativeQueue() { const jobs = new Map(); const pendingIds = []; let activeJobId = null; return { enqueue(job) { if (!job || !job.id) { throw new Error('Image derivative job requires an id.'); } const persisted = { ...job, status: job.status ?? 'PENDING', error: null, derivatives: job.derivatives ?? [], }; jobs.set(job.id, persisted); pendingIds.push(job.id); return persisted; }, claimNext() { const nextId = pendingIds.shift(); if (!nextId) return null; const current = jobs.get(nextId); if (!current) return null; activeJobId = nextId; const claimed = { ...current, status: 'PROCESSING', error: null, startedAt: new Date(), }; jobs.set(nextId, claimed); return claimed; }, getCurrentJob() { if (!activeJobId) return null; return jobs.get(activeJobId) ?? null; }, getJob(id) { return jobs.get(id) ?? null; }, updateJob(id, updates) { const current = jobs.get(id); if (!current) return null; const next = { ...current, ...updates, status: updates.status ?? current.status, }; jobs.set(id, next); if (next.status === 'COMPLETED' || next.status === 'FAILED') { if (activeJobId === id) { activeJobId = null; } } return next; }, }; } export async function processNextImageDerivativeJob({ queue, loadSource, processor }) { if (!queue || typeof queue.claimNext !== 'function') { throw new TypeError('Image derivative queue is required.'); } const claimed = queue.getCurrentJob() ?? queue.claimNext(); if (!claimed) { return null; } const result = await runImageDerivativeJob({ job: claimed, loadSource, processor }); queue.updateJob(claimed.id, result); return result; } export async function runImageDerivativeJob({ job, loadSource, processor }) { if (!job || job.type !== 'IMAGE_DERIVATIVES') { throw new Error('Unsupported image derivative job.'); } const processingJob = { ...job, status: 'PROCESSING', error: null }; try { const source = await loadSource(job.sourceKey); const derivatives = await processor.process(source); return { ...processingJob, status: 'COMPLETED', derivatives, completedAt: new Date(), }; } catch (error) { return { ...processingJob, status: 'FAILED', error: error instanceof Error ? error.message : 'Image derivative processing failed.', failedAt: new Date(), }; } } export async function processNextPersistentImageDerivativeJob({ jobRepository, loadSource, processor }) { const claimed = await jobRepository.claimNext(); if (!claimed) return null; const job = { ...claimed, type: 'IMAGE_DERIVATIVES' }; const result = await runImageDerivativeJob({ job, loadSource, processor }); if (result.status === 'COMPLETED') { await jobRepository.complete(claimed.id, result.derivatives); } else { await jobRepository.fail(claimed.id, result.error); } return result; }