core/apps/webapp/app/bullmq/utils/job-finder.ts
Harshith Mullapudi f39c7cc6d0
feat: remove trigger and run base on bullmq (#126)
* feat: remove trigger and run base on bullmq
* fix: telemetry and trigger deploymen
* feat: add Ollama container and update ingestion status for unchanged documents
* feat: add logger to bullmq workers
* 1. Remove chat and deep-search from trigger
2. Add ai/sdk for chat UI
3. Added a better model manager

* refactor: simplify clustered graph query and add stop conditions for AI responses

* fix: streaming

* fix: docker docs

---------

Co-authored-by: Manoj <saimanoj58@gmail.com>
2025-10-26 12:56:12 +05:30

133 lines
3.0 KiB
TypeScript

/**
* BullMQ Job Finder Utilities
*
* Helper functions to find, retrieve, and cancel BullMQ jobs
*/
interface JobInfo {
id: string;
isCompleted: boolean;
status?: string;
}
/**
* Get all active queues
*/
async function getAllQueues() {
const {
ingestQueue,
documentIngestQueue,
conversationTitleQueue,
sessionCompactionQueue,
} = await import("../queues");
return [
ingestQueue,
documentIngestQueue,
conversationTitleQueue,
sessionCompactionQueue,
];
}
/**
* Find jobs by tags (metadata stored in job data)
* Since BullMQ doesn't have native tag support like Trigger.dev,
* we search through jobs and check if their data contains the required identifiers
*/
export async function getJobsByTags(
tags: string[],
taskIdentifier?: string,
): Promise<JobInfo[]> {
const queues = await getAllQueues();
const matchingJobs: JobInfo[] = [];
for (const queue of queues) {
// Skip if taskIdentifier is specified and doesn't match queue name
if (taskIdentifier && !queue.name.includes(taskIdentifier)) {
continue;
}
// Get all active and waiting jobs
const [active, waiting, delayed] = await Promise.all([
queue.getActive(),
queue.getWaiting(),
queue.getDelayed(),
]);
const allJobs = [...active, ...waiting, ...delayed];
for (const job of allJobs) {
// Check if job data contains all required tags
const jobData = job.data as any;
const matchesTags = tags.every(
(tag) =>
job.id?.includes(tag) ||
jobData.userId === tag ||
jobData.workspaceId === tag ||
jobData.queueId === tag,
);
if (matchesTags) {
const state = await job.getState();
matchingJobs.push({
id: job.id!,
isCompleted: state === "completed" || state === "failed",
status: state,
});
}
}
}
return matchingJobs;
}
/**
* Get a specific job by ID across all queues
*/
export async function getJobById(jobId: string): Promise<JobInfo | null> {
const queues = await getAllQueues();
for (const queue of queues) {
try {
const job = await queue.getJob(jobId);
if (job) {
const state = await job.getState();
return {
id: job.id!,
isCompleted: state === "completed" || state === "failed",
status: state,
};
}
} catch {
// Job not in this queue, continue
continue;
}
}
return null;
}
/**
* Cancel a job by ID
*/
export async function cancelJobById(jobId: string): Promise<void> {
const queues = await getAllQueues();
for (const queue of queues) {
try {
const job = await queue.getJob(jobId);
if (job) {
const state = await job.getState();
// Only remove if not already completed
if (state !== "completed" && state !== "failed") {
await job.remove();
}
return;
}
} catch {
// Job not in this queue, continue
continue;
}
}
}