70 lines
2.9 KiB
JavaScript
70 lines
2.9 KiB
JavaScript
const { Worker } = require('bullmq');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { imageQueue, connection } = require('./imageQueue');
|
|
const { resizeTo8K } = require('../utils/imageHelper');
|
|
const { injectGPSCoordinates } = require('../utils/exifHelper');
|
|
const Asset = require('../models/Asset');
|
|
const Scene = require('../models/Scene');
|
|
|
|
/**
|
|
* Khởi tạo Worker để xử lý hàng đợi 'image-processing'
|
|
*/
|
|
const imageWorker = new Worker('image-processing', async (job) => {
|
|
const { tempFilePath, processedFilePath, latitude, longitude, assetId, sceneId } = job.data;
|
|
|
|
console.log(`[Worker] Bắt đầu xử lý Job ${job.id} cho Scene: ${sceneId}`);
|
|
|
|
try {
|
|
// Quy trình tối giản: Chỉ Resize ảnh sang 8K (Sharp)
|
|
// Vì người dùng đã stitch ảnh từ Insta360 Studio, file upload đã là Equirectangular JPEG.
|
|
await resizeTo8K(tempFilePath, processedFilePath);
|
|
|
|
// 3. Chèn GPS Metadata
|
|
await injectGPSCoordinates(processedFilePath, latitude, longitude);
|
|
|
|
// 4. Cập nhật đường dẫn file thực tế vào Database
|
|
// Lúc này ảnh đã sẵn sàng để phục vụ (8K)
|
|
await Asset.findByIdAndUpdate(assetId, { filePath: processedFilePath });
|
|
await Scene.findByIdAndUpdate(sceneId, {
|
|
scene_url: processedFilePath,
|
|
status: 'completed' // Xử lý xong
|
|
});
|
|
|
|
// 5. Dọn dẹp file tạm
|
|
await fs.promises.unlink(tempFilePath).catch(() => {});
|
|
|
|
console.log(`[Worker] Hoàn tất xử lý Job ${job.id}`);
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error(`[Worker Error] Job ${job.id} thất bại:`, error.message);
|
|
await Scene.findByIdAndUpdate(sceneId, { status: 'failed' }); // Đánh dấu lỗi
|
|
throw error; // Đẩy lỗi để BullMQ thực hiện retry
|
|
}
|
|
}, { connection });
|
|
|
|
imageWorker.on('completed', (job) => {
|
|
console.log(`Job ${job.id} đã hoàn thành thành công.`);
|
|
});
|
|
|
|
imageWorker.on('failed', (job, err) => {
|
|
console.error(`Job ${job.id} thất bại sau nhiều lần thử: ${err.message}`);
|
|
});
|
|
|
|
// Khi khởi động Worker, thực hiện dọn dẹp các job "stalled" hoặc dữ liệu rác
|
|
// để đảm bảo Redis luôn sạch sẽ khi hệ thống khởi động lại.
|
|
imageWorker.on('ready', async () => {
|
|
console.log('[Worker] Sẵn sàng xử lý hàng đợi.');
|
|
try {
|
|
// Xóa các job hoàn thành quá 1 giờ và job thất bại quá 24 giờ
|
|
// (Bổ trợ thêm cho cơ chế tự động dọn dẹp của Queue)
|
|
await imageQueue.clean(3600000, 1000, 'completed');
|
|
await imageQueue.clean(86400000, 1000, 'failed');
|
|
|
|
console.log('[Worker] Đã dọn dẹp các job cũ không cần thiết trong Redis.');
|
|
} catch (err) {
|
|
console.error('[Worker Cleanup Error]:', err.message);
|
|
}
|
|
});
|
|
|
|
module.exports = imageWorker; |