91 lines
4.1 KiB
JavaScript
91 lines
4.1 KiB
JavaScript
const mongoose = require('mongoose');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const connectDB = require('../config/db');
|
|
const User = require('../models/User');
|
|
const Scene = require('../models/Scene');
|
|
const Asset = require('../models/Asset');
|
|
const Hotspot = require('../models/Hotspot');
|
|
|
|
/**
|
|
* Script dọn dẹp dữ liệu rác (orphaned data)
|
|
* Xóa các Scene, Asset và File vật lý của những người dùng đã bị xóa khỏi hệ thống.
|
|
* Đồng thời dọn dẹp các Asset "mồ côi" không còn được gắn vào bất kỳ Scene nào.
|
|
*/
|
|
const cleanup = async () => {
|
|
try {
|
|
console.log('--- Bắt đầu quy trình dọn dẹp dữ liệu rác ---');
|
|
await connectDB();
|
|
|
|
// 1. Lấy danh sách tất cả ID người dùng hiện đang tồn tại
|
|
const validUserIds = await User.distinct('_id');
|
|
console.log(`- Tìm thấy ${validUserIds.length} người dùng hợp lệ.`);
|
|
|
|
// 2. Tìm các Scene mồ côi (Người tạo không còn tồn tại)
|
|
const orphanedScenes = await Scene.find({ createdBy: { $nin: validUserIds } });
|
|
const orphanedSceneIds = orphanedScenes.map(s => s._id);
|
|
console.log(`- Tìm thấy ${orphanedSceneIds.length} cảnh (Scene) mồ côi.`);
|
|
|
|
// 3. Xóa các Hotspot liên quan đến các Scene mồ côi
|
|
// Xóa cả hotspot xuất phát từ và trỏ đến các scene bị xóa
|
|
const hotspotResult = await Hotspot.deleteMany({
|
|
$or: [
|
|
{ parent_scene_id: { $in: orphanedSceneIds } },
|
|
{ target_scene_id: { $in: orphanedSceneIds } }
|
|
]
|
|
});
|
|
console.log(`- Đã xóa ${hotspotResult.deletedCount} liên kết Hotspot liên quan.`);
|
|
|
|
// 4. Xóa các Scene mồ côi trong DB
|
|
const sceneResult = await Scene.deleteMany({ _id: { $in: orphanedSceneIds } });
|
|
console.log(`- Đã xóa ${sceneResult.deletedCount} bản ghi Scene trong Database.`);
|
|
|
|
// 5. Tìm các Asset mồ côi (Người upload không tồn tại HOẶC không có Scene nào liên kết)
|
|
// Chúng ta lấy danh sách assetId đang được sử dụng bởi các Scene còn lại
|
|
const usedAssetIds = await Scene.distinct('assetId');
|
|
|
|
// Để an toàn, chỉ xóa các Asset không liên kết nếu chúng đã tồn tại hơn 2 giờ
|
|
// (Tránh xóa nhầm ảnh đang trong hàng đợi xử lý của Worker)
|
|
const safeDate = new Date(Date.now() - 2 * 3600 * 1000);
|
|
|
|
const orphanedAssets = await Asset.find({
|
|
$or: [
|
|
{ uploadedBy: { $nin: validUserIds } }, // User đã bị xóa
|
|
{
|
|
$and: [
|
|
{ _id: { $nin: usedAssetIds } }, // Không có scene nào trỏ tới
|
|
{ createdAt: { $lt: safeDate } } // Đã quá 2 giờ
|
|
]
|
|
}
|
|
]
|
|
});
|
|
console.log(`- Tìm thấy ${orphanedAssets.length} ảnh (Asset) mồ côi hoặc không liên kết.`);
|
|
|
|
// 6. Xóa tệp tin vật lý và bản ghi Asset
|
|
let filesDeleted = 0;
|
|
for (const asset of orphanedAssets) {
|
|
if (asset.filePath) {
|
|
try {
|
|
await fs.promises.unlink(asset.filePath);
|
|
filesDeleted++;
|
|
} catch (e) {
|
|
if (e.code !== 'ENOENT') console.error(` [Lỗi] Không thể xóa file: ${asset.filePath}`);
|
|
}
|
|
}
|
|
await Asset.findByIdAndDelete(asset._id);
|
|
}
|
|
console.log(`- Đã dọn dẹp ${filesDeleted} tệp tin vật lý.`);
|
|
console.log(`- Đã xóa ${orphanedAssets.length} bản ghi Asset trong Database.`);
|
|
|
|
console.log('--- Hoàn tất dọn dẹp! Hệ thống đã sạch sẽ. ---');
|
|
|
|
mongoose.connection.close();
|
|
process.exit(0);
|
|
} catch (err) {
|
|
console.error('Lỗi nghiêm trọng khi dọn dẹp:', err.message);
|
|
if (mongoose.connection) mongoose.connection.close();
|
|
process.exit(1);
|
|
}
|
|
};
|
|
|
|
cleanup(); |