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

This commit is contained in:
2026-09-08 22:00:18 -04:00
parent b00bd388a9
commit 7be79f4840
8 changed files with 1773 additions and 1 deletions
+3
View File
@@ -22,6 +22,7 @@ import { createInventoryItemService } from '../modules/inventory/services/invent
import { createPublicInventoryService } from '../modules/inventory/services/public-inventory-service.js';
import { createPublicImageService } from '../modules/inventory/services/public-image-service.js';
import { createInventoryImageRepository } from '../modules/inventory/repositories/inventory-image-repository.js';
import { createImageDerivativeJobRepository } from '../modules/inventory/repositories/image-derivative-job-repository.js';
import { createInventoryImageService } from '../modules/inventory/services/inventory-image-service.js';
import { createLocalImageStorage } from '../infrastructure/images/local-image-storage.js';
import { createConditionRepository } from '../modules/inventory/repositories/condition-repository.js';
@@ -51,6 +52,7 @@ async function startServer() {
const productRepository = createProductRepository(database.db);
const inventoryItemRepository = createInventoryItemRepository(database.db);
const inventoryImageRepository = createInventoryImageRepository(database.db);
const imageDerivativeJobRepository = createImageDerivativeJobRepository(database.db);
const listingRepository = createListingRepository(database.db);
const sellerRepository = createSellerRepository(database.db);
const conditionRepository = createConditionRepository(database.db);
@@ -104,6 +106,7 @@ async function startServer() {
publicInventoryService: createPublicInventoryService({ inventoryItemRepository, publicImageService }),
inventoryImageService: createInventoryImageService({
imageStorage: createLocalImageStorage(process.env.IMAGE_STORAGE_ROOT ?? '.local/image-storage'),
imageDerivativeJobRepository,
inventoryImageRepository,
}),
listingService: createListingService({ listingRepository, inventoryImageRepository }),
@@ -264,6 +264,22 @@ export const inventoryImages = pgTable(
(table) => [index('inventory_images_inventory_item_id_index').on(table.inventoryItemId)],
);
export const imageDerivativeJobs = pgTable(
'image_derivative_jobs',
{
id: uuid('id').defaultRandom().primaryKey(),
inventoryImageId: uuid('inventory_image_id')
.notNull()
.references(() => inventoryImages.id),
sourceKey: text('source_key').notNull(),
status: text('status').default('PENDING').notNull(),
derivatives: jsonb('derivatives').default([]).notNull(),
error: text('error'),
...timestamps,
},
(table) => [index('image_derivative_jobs_image_id_index').on(table.inventoryImageId)],
);
export const listings = pgTable('listings', {
id: uuid('id').defaultRandom().primaryKey(),
inventoryItemId: uuid('inventory_item_id')
@@ -0,0 +1,20 @@
import { asc, eq } from 'drizzle-orm';
import { imageDerivativeJobs } from '../../../infrastructure/database/schema.js';
export function createImageDerivativeJobRepository(db) {
return {
async create(job) {
const [createdJob] = await db.insert(imageDerivativeJobs).values(job).returning();
return createdJob;
},
async listByImageId(inventoryImageId) {
return db
.select()
.from(imageDerivativeJobs)
.where(eq(imageDerivativeJobs.inventoryImageId, inventoryImageId))
.orderBy(asc(imageDerivativeJobs.createdAt));
},
};
}
@@ -1,7 +1,7 @@
import { createApplicationError } from '../../../shared/errors/application-error.js';
import { validateImageSignature, validateInventoryImageMetadata } from '../domain/inventory-image.js';
export function createInventoryImageService({ inventoryImageRepository, imageStorage }) {
export function createInventoryImageService({ inventoryImageRepository, imageDerivativeJobRepository, imageStorage }) {
return {
async create(input) {
validateInventoryImageMetadata(input);
@@ -14,6 +14,12 @@ export function createInventoryImageService({ inventoryImageRepository, imageSto
throw createApplicationError('INVENTORY_ITEM_NOT_FOUND', 'Inventory item was not found.', 404);
}
await imageDerivativeJobRepository?.create({
inventoryImageId: image.id,
sourceKey: image.storageKey,
status: 'PENDING',
});
return image;
},