130 lines
3.1 KiB
JavaScript
130 lines
3.1 KiB
JavaScript
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;
|
|
} |