Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/integrations/filePreviewQueue.server.ts
T

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(() => {});
}
}
}