feat(ai-image): AI生图开发

This commit is contained in:
2026-09-27 22:40:52 +08:00
parent e670d06ca6
commit a29dd92676
105 changed files with 9943 additions and 361 deletions
+33
View File
@@ -29,6 +29,10 @@ import {
syncPlatformCatalog,
} from './platform-catalog-sync.js';
import { runProductAiTask } from './product-ai.js';
import { markAspectRatioDerivativeFailed, runAspectRatioDerivative } from './media-aspect-ratio.js';
import { markWatermarkDerivativeFailed, runWatermarkDerivative } from './media-watermark.js';
import { classifyAiEditFailure, markMediaAiEditFailed, runMediaAiEdit } from './media-ai-edit.js';
import { archiveExpiredMissingOnlineProducts, markOnlineProductSyncFailed, runOnlineProductSync, type OnlineProductSyncJob } from './online-product-sync.js';
const connection = new Redis(workerConfig.redisUrl, {
maxRetriesPerRequest: null,
@@ -82,6 +86,18 @@ const worker = new Worker<OutboxJob | PlatformCatalogJob>(
await syncPlatformCatalog(database, job.data as PlatformCatalogJob);
} else if (job.name === 'product_ai_task.requested') {
await runProductAiTask(database, job.data as OutboxJob);
} else if (job.name === 'media.aspect_ratio_derivative.requested') {
await runAspectRatioDerivative(
database,
objectStorage,
job.data as OutboxJob,
);
} else if (job.name === 'media.watermark_derivative.requested') {
await runWatermarkDerivative(database, objectStorage, job.data as OutboxJob);
} else if (job.name === 'media.ai_edit.requested') {
await runMediaAiEdit(database, objectStorage, job.data as OutboxJob);
} else if (job.name === 'platform_product_sync.requested') {
await runOnlineProductSync(database, job.data as OnlineProductSyncJob);
} else if (job.name === 'store_credential_verification.requested') {
await verifyStoreCredentials(
database,
@@ -160,6 +176,14 @@ worker.on('failed', (job, error) => {
database,
job.data as PlatformCatalogJob,
);
} else if (job.name === 'media.aspect_ratio_derivative.requested') {
void markAspectRatioDerivativeFailed(database, job.data as OutboxJob);
} else if (job.name === 'media.watermark_derivative.requested') {
void markWatermarkDerivativeFailed(database, job.data as OutboxJob);
} else if (job.name === 'media.ai_edit.requested') {
void markMediaAiEditFailed(database, job.data as OutboxJob, classifyAiEditFailure(error));
} else if (job.name === 'platform_product_sync.requested') {
void markOnlineProductSyncFailed(database, job.data as OnlineProductSyncJob, error);
} else if (job.name === 'store_credential_verification.requested') {
void markUnavailable(database, job.data as StoreVerificationJob, error);
} else if (
@@ -376,6 +400,7 @@ async function markUnavailable(
let dispatcherTimer: ReturnType<typeof setInterval> | undefined;
let mediaCleanupTimer: ReturnType<typeof setInterval> | undefined;
let platformCatalogTimer: ReturnType<typeof setInterval> | undefined;
let onlineProductArchiveTimer: ReturnType<typeof setInterval> | undefined;
async function bootstrap() {
await queue.waitUntilReady();
await platformQueue.waitUntilReady();
@@ -384,6 +409,7 @@ async function bootstrap() {
await dispatcher.dispatchBatch();
await platformDispatcher.dispatchBatch();
await platformScheduler.run();
await archiveExpiredMissingOnlineProducts(database);
dispatcherTimer = setInterval(() => {
void dispatcher.dispatchBatch().catch((error: unknown) => {
console.error(
@@ -408,6 +434,12 @@ async function bootstrap() {
}),
60_000,
);
onlineProductArchiveTimer = setInterval(
() => void archiveExpiredMissingOnlineProducts(database).catch((error: unknown) => {
console.error('online_product_archive_failed', error instanceof Error ? error.message : error);
}),
60 * 60_000,
);
void mediaUploadCleanup.run().catch((error: unknown) => {
console.error(
'media_upload_cleanup_startup_failed',
@@ -439,6 +471,7 @@ async function shutdown() {
if (dispatcherTimer) clearInterval(dispatcherTimer);
if (mediaCleanupTimer) clearInterval(mediaCleanupTimer);
if (platformCatalogTimer) clearInterval(platformCatalogTimer);
if (onlineProductArchiveTimer) clearInterval(onlineProductArchiveTimer);
await worker.close();
await platformWorker.close();
await queue.close();