import { Processor, WorkerHost } from "@nestjs/bullmq"; import { Logger } from "@nestjs/common"; import { Job } from "bullmq"; import { OllamaEmbeddingService } from "../services/ollama-embedding.service"; import { EmbeddingJobData } from "./embedding-queue.service"; /** * Processor for embedding generation jobs * * This worker processes queued embedding jobs and generates * embeddings for knowledge entries using Ollama. */ @Processor("embeddings") export class EmbeddingProcessor extends WorkerHost { private readonly logger = new Logger(EmbeddingProcessor.name); constructor(private readonly embeddingService: OllamaEmbeddingService) { super(); } /** * Process an embedding generation job * * @param job - The embedding job to process */ async process(job: Job): Promise { const { entryId, content, model } = job.data; this.logger.log(`Processing embedding job ${job.id ?? "unknown"} for entry ${entryId}`); try { const options: { model?: string } = {}; if (model !== undefined) { options.model = model; } await this.embeddingService.generateAndStoreEmbedding(entryId, content, options); this.logger.log( `Successfully generated embedding for entry ${entryId} (job: ${job.id ?? "unknown"})` ); } catch (error) { this.logger.error( `Failed to generate embedding for entry ${entryId} (job: ${job.id ?? "unknown"})`, error ); throw error; // Re-throw to trigger retry logic } } /** * Handle successful job completion * * @param job - The completed job */ onCompleted(job: Job): void { this.logger.log( `Successfully generated embedding for entry ${job.data.entryId} (job: ${job.id ?? "unknown"})` ); } /** * Handle job failure * * @param job - The failed job * @param error - The error that caused the failure */ onFailed(job: Job, error: Error): void { this.logger.error( `Failed to generate embedding for entry ${job.data.entryId} (job: ${job.id ?? "unknown"}) after ${job.attemptsMade.toString()} attempts`, error ); } /** * Alias for process to match test expectations */ async processEmbedding(job: Job): Promise { return this.process(job); } /** * Alias for onCompleted to match test expectations */ handleCompleted(job: Job): void { this.onCompleted(job); } /** * Alias for onFailed to match test expectations */ handleFailed(job: Job, error: Error): void { this.onFailed(job, error); } }