feat: claim durable image derivative jobs
Quality / test (push) Canceled after 0s

This commit is contained in:
2026-09-08 22:04:02 -04:00
parent 7be79f4840
commit abd574293b
4 changed files with 134 additions and 3 deletions
@@ -1,6 +1,9 @@
import { asc, eq } from 'drizzle-orm';
import { and, asc, eq } from 'drizzle-orm';
import { imageDerivativeJobs } from '../../../infrastructure/database/schema.js';
import {
imageDerivativeJobs,
inventoryImages,
} from '../../../infrastructure/database/schema.js';
export function createImageDerivativeJobRepository(db) {
return {
@@ -16,5 +19,71 @@ export function createImageDerivativeJobRepository(db) {
.where(eq(imageDerivativeJobs.inventoryImageId, inventoryImageId))
.orderBy(asc(imageDerivativeJobs.createdAt));
},
async claimNext() {
return db.transaction(async (tx) => {
const [job] = await tx
.select()
.from(imageDerivativeJobs)
.where(eq(imageDerivativeJobs.status, 'PENDING'))
.orderBy(asc(imageDerivativeJobs.createdAt))
.limit(1)
.for('update', { skipLocked: true });
if (!job) return null;
const [claimed] = await tx
.update(imageDerivativeJobs)
.set({ status: 'PROCESSING', updatedAt: new Date(), error: null })
.where(and(
eq(imageDerivativeJobs.id, job.id),
eq(imageDerivativeJobs.status, 'PENDING'),
))
.returning();
if (claimed) {
await tx
.update(inventoryImages)
.set({ processingStatus: 'PROCESSING', updatedAt: new Date() })
.where(eq(inventoryImages.id, claimed.inventoryImageId));
}
return claimed ?? null;
});
},
async complete(id, derivatives) {
const [completed] = await db
.update(imageDerivativeJobs)
.set({ status: 'COMPLETED', derivatives, updatedAt: new Date(), error: null })
.where(and(eq(imageDerivativeJobs.id, id), eq(imageDerivativeJobs.status, 'PROCESSING')))
.returning();
if (completed) {
await db
.update(inventoryImages)
.set({ processingStatus: 'COMPLETED', updatedAt: new Date() })
.where(eq(inventoryImages.id, completed.inventoryImageId));
}
return completed ?? null;
},
async fail(id, message) {
const [failed] = await db
.update(imageDerivativeJobs)
.set({ status: 'FAILED', error: message, updatedAt: new Date() })
.where(and(eq(imageDerivativeJobs.id, id), eq(imageDerivativeJobs.status, 'PROCESSING')))
.returning();
if (failed) {
await db
.update(inventoryImages)
.set({ processingStatus: 'FAILED', updatedAt: new Date() })
.where(eq(inventoryImages.id, failed.inventoryImageId));
}
return failed ?? null;
},
};
}