UNPKG

@fdm-monster/server

Version:

FDM Monster is a bulk OctoPrint, Klipper, PrusaLink and BambuLab manager to set up, configure and monitor 3D printers. Our aim is to provide neat overview over your farm.

90 lines (89 loc) 3.84 kB
import { PrintJob } from "../entities/print-job.entity.js"; //#region src/tasks/print-job-analysis.task.ts /** * Background task to analyze pending print jobs * Runs periodically to extract metadata from uploaded files */ var PrintJobAnalysisTask = class PrintJobAnalysisTask { logger; printJobRepository; constructor(loggerFactory, printJobService, fileAnalysisService, fileStorageService, typeormService) { this.printJobService = printJobService; this.fileAnalysisService = fileAnalysisService; this.fileStorageService = fileStorageService; this.logger = loggerFactory(PrintJobAnalysisTask.name); this.printJobRepository = typeormService.getDataSource().getRepository(PrintJob); } async run() { try { const pendingJobs = await this.printJobRepository.find({ where: [{ analysisState: "NOT_ANALYZED", status: "PENDING" }, { analysisState: "ANALYZING" }], take: 10 }); if (pendingJobs.length === 0) return; this.logger.log(`Found ${pendingJobs.length} print job(s) to analyze`); for (const job of pendingJobs) try { await this.analyzeJob(job); } catch (error) { this.logger.error(`Failed to analyze job ${job.id}: ${job.fileName}`, error); job.analysisState = "FAILED"; job.statusReason = `Analysis failed: ${error instanceof Error ? error.message : "Unknown error"}`; await this.printJobRepository.save(job); } this.logger.log(`Completed analysis of ${pendingJobs.length} print job(s)`); } catch (error) { this.logger.error("Failed to run print job analysis task", error); } } async analyzeJob(job) { this.logger.log(`Analyzing print job ${job.id}: ${job.fileName}`); job.analysisState = "ANALYZING"; await this.printJobRepository.save(job); if (!job.fileStorageId) throw new Error("Job has no fileStorageId - cannot analyze"); const cachedMetadata = await this.fileStorageService.loadMetadata(job.fileStorageId); let metadata; let thumbnails = []; if (cachedMetadata) { this.logger.log(`Using cached metadata for job ${job.id} (storageId: ${job.fileStorageId})`); metadata = cachedMetadata; thumbnails = []; } else { const filePath = await this.resolveFilePath(job); if (!filePath) throw new Error("File path could not be resolved"); if (!await this.fileAnalysisService.needsAnalysis(filePath)) throw new Error(`File not found: ${filePath}`); const analysisResult = await this.fileAnalysisService.analyzeFile(filePath); metadata = analysisResult.metadata; thumbnails = analysisResult.thumbnails; let thumbnailMetadata = []; if (thumbnails && thumbnails.length > 0) { thumbnailMetadata = await this.fileStorageService.saveThumbnails(job.fileStorageId, thumbnails); this.logger.log(`Saved ${thumbnailMetadata.length} thumbnail(s) for job ${job.id}`); } const fileHash = job.fileHash || void 0; await this.fileStorageService.saveMetadata(job.fileStorageId, metadata, fileHash, job.fileName, thumbnailMetadata); this.logger.log(`Cached metadata JSON for job ${job.id}`); } await this.printJobService.handleFileAnalyzed(job.id, metadata, thumbnails); this.logger.log(`Successfully analyzed job ${job.id}: ${job.fileName}`); } async resolveFilePath(job) { if (job.fileStorageId) try { if (!await this.fileStorageService.fileExists(job.fileStorageId)) { this.logger.warn(`File ${job.fileStorageId} not found in storage for job ${job.id}`); return null; } return this.fileStorageService.getFilePath(job.fileStorageId); } catch (error) { this.logger.error(`Failed to resolve file path for job ${job.id}: ${error}`); return null; } this.logger.debug(`Job ${job.id} has no fileStorageId - cannot analyze remotely stored file`); return null; } }; //#endregion export { PrintJobAnalysisTask }; //# sourceMappingURL=print-job-analysis.task.js.map