75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
// Producer-side helper for the toolctrl.file-preview BullMQ queue. Web routes
|
|
// call enqueueFilePreview(...) after a successful upload (and on the "regenerate
|
|
// preview" action) to trigger asynchronous preview generation in the worker.
|
|
// Mirrors fileScanQueue.server.ts so the queue lifecycle is the same shared
|
|
// pattern. Unlike the scan queue there is no enable-flag: preview generation is
|
|
// always desired; if Redis is unreachable the enqueue is a no-op and the file
|
|
// simply keeps previewStatus=pending until re-triggered.
|
|
|
|
import {
|
|
buildFilePreviewJob,
|
|
enqueueJob,
|
|
queueNames,
|
|
resolveRedisConnectionOptions,
|
|
resolveRedisConnectionOptionsFromProcessEnv,
|
|
type RedisConnectionEnv,
|
|
type TypedQueue,
|
|
} from "@toolctrl/queue";
|
|
|
|
export type EnqueueFilePreviewInput = {
|
|
fileId: string;
|
|
tenantId: string;
|
|
bucket: string;
|
|
storageKey: string;
|
|
mimeType: string;
|
|
metadata?: Record<string, unknown>;
|
|
};
|
|
|
|
export type EnqueueFilePreviewResult = { enqueued: true; jobId?: string } | { enqueued: false; reason: "queue-unavailable" };
|
|
|
|
type Dependencies = {
|
|
env?: RedisConnectionEnv;
|
|
queue?: TypedQueue<typeof queueNames.filePreview>;
|
|
};
|
|
|
|
export async function enqueueFilePreview(input: EnqueueFilePreviewInput, dependencies: Dependencies = {}): Promise<EnqueueFilePreviewResult> {
|
|
let queue = dependencies.queue;
|
|
let shouldCloseQueue = false;
|
|
const connection = queue
|
|
? undefined
|
|
: dependencies.env
|
|
? resolveRedisConnectionOptions({ env: dependencies.env })
|
|
: resolveRedisConnectionOptionsFromProcessEnv();
|
|
|
|
if (!queue && !connection) {
|
|
return { enqueued: false, reason: "queue-unavailable" };
|
|
}
|
|
|
|
if (!queue && connection) {
|
|
const queueRuntimeModule = "@toolctrl/queue/runtime";
|
|
const { createQueue } = (await import(/* @vite-ignore */ queueRuntimeModule)) as typeof import("@toolctrl/queue/runtime");
|
|
queue = createQueue(queueNames.filePreview, { connection });
|
|
shouldCloseQueue = true;
|
|
}
|
|
if (!queue) {
|
|
return { enqueued: false, reason: "queue-unavailable" };
|
|
}
|
|
|
|
try {
|
|
const descriptor = buildFilePreviewJob({
|
|
fileId: input.fileId,
|
|
tenantId: input.tenantId,
|
|
bucket: input.bucket,
|
|
storageKey: input.storageKey,
|
|
mimeType: input.mimeType,
|
|
metadata: input.metadata,
|
|
});
|
|
const job = await enqueueJob(queue, descriptor, { tenantId: input.tenantId });
|
|
return { enqueued: true, jobId: typeof job.id === "string" ? job.id : undefined };
|
|
} finally {
|
|
if (shouldCloseQueue && queue) {
|
|
await queue.close().catch(() => {});
|
|
}
|
|
}
|
|
}
|