119 lines
4.7 KiB
JavaScript
119 lines
4.7 KiB
JavaScript
const pool = require("../db/pool.js");
|
|
const { DeleteObjectCommand } = require("@aws-sdk/client-s3");
|
|
const onPremiseClient = require('../config/onPremiseClient.js');
|
|
const cloudClient = require('../config/cloudClient.js');
|
|
const storageClients = {
|
|
'ONPREMISE': onPremiseClient,
|
|
'CLOUD': cloudClient
|
|
};
|
|
const s3 = storageClients[process.env.DEPLOYMENT_TYPE || 'ONPREMISE'];
|
|
const env = process.env.NODE_ENV;
|
|
const tbData = env === 'production' ? 'tb_data' : '_test_tb_data';
|
|
|
|
async function runAutoClean() {
|
|
const client = await pool.connect();
|
|
try {
|
|
console.log("⏰ Running auto clean batch job...");
|
|
|
|
// 1. 글로벌 보관 정책 조회
|
|
const policyRes = await client.query("SELECT * FROM ver4.tb_system_policy WHERE policy_key = 'GLOBAL_DELETE_POLICY'");
|
|
if (policyRes.rows.length === 0 || !policyRes.rows[0].is_active) {
|
|
console.log("⏰ Auto clean policy is disabled or not found.");
|
|
return;
|
|
}
|
|
|
|
const { limit_file_count, limit_days } = policyRes.rows[0];
|
|
|
|
// 2. 삭제 대상 파일 검색 (각 현장의 파일 개수가 limit_file_count 미만이고, limit_days 일이 지난 파일)
|
|
const targetQuery = `
|
|
SELECT data_id, project_id, object_key, preview_key, popup_key, thumbnail_key,
|
|
path1, path2, path3, path4, path5, path6, path7, path8, data_depth, is_folder
|
|
FROM ver4.${tbData}
|
|
WHERE is_folder = false AND is_removed = false
|
|
AND project_id IN (
|
|
SELECT project_id
|
|
FROM ver4.${tbData}
|
|
WHERE is_folder = false AND is_removed = false
|
|
GROUP BY project_id
|
|
HAVING COUNT(*) < $1
|
|
)
|
|
AND create_date < NOW() - CAST($2 || ' days' AS INTERVAL);
|
|
`;
|
|
const targets = await client.query(targetQuery, [limit_file_count, limit_days]);
|
|
|
|
console.log(`⏰ Found ${targets.rows.length} files to clean up.`);
|
|
|
|
for (const file of targets.rows) {
|
|
let success = true;
|
|
let keysToDelete = [];
|
|
if (file.object_key) keysToDelete.push(file.object_key);
|
|
if (file.preview_key) keysToDelete.push(file.preview_key);
|
|
if (file.popup_key) keysToDelete.push(file.popup_key);
|
|
if (file.thumbnail_key) keysToDelete.push(file.thumbnail_key);
|
|
|
|
// S3 실물 파일 삭제
|
|
for (const key of keysToDelete) {
|
|
try {
|
|
const command = new DeleteObjectCommand({
|
|
Bucket: file.project_id, // 현장 ID를 버킷 명으로 사용함
|
|
Key: key
|
|
});
|
|
await s3.send(command);
|
|
} catch (s3Err) {
|
|
console.error(`❌ S3 Delete Error [Key: ${key}]:`, s3Err.message);
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
// DB 메타 정보 완전 제거
|
|
try {
|
|
await client.query(`DELETE FROM ver4.${tbData} WHERE data_id = $1`, [file.data_id]);
|
|
} catch (dbErr) {
|
|
console.error(`❌ DB Delete Error [DataID: ${file.data_id}]:`, dbErr.message);
|
|
success = false;
|
|
}
|
|
|
|
// 삭제 경로 조합
|
|
let cleanPath = '';
|
|
for (let i = 1; i <= file.data_depth; i++) {
|
|
if (file[`path${i}`]) cleanPath += '/' + file[`path${i}`];
|
|
}
|
|
|
|
// 로그 기록
|
|
const criteria = `보관수량 ${limit_file_count}개 미만 / 기한 ${limit_days}일 경과`;
|
|
await client.query(`
|
|
INSERT INTO ver4.tb_auto_clean_log (clean_date, project_id, clean_path, criteria_info, result_status)
|
|
VALUES (CURRENT_TIMESTAMP, 'SYSTEM', $1, $2, $3);
|
|
`, [cleanPath, criteria, success ? 'SUCCESS' : 'FAILED']);
|
|
}
|
|
console.log("⏰ Auto clean batch job finished successfully.");
|
|
} catch (err) {
|
|
console.error("❌ Auto Clean Batch Error:", err);
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
// 매일 자정에 한 번 가동하는 타이머 등록 함수
|
|
function startScheduler() {
|
|
const now = new Date();
|
|
const target = new Date();
|
|
target.setHours(0, 0, 0, 0);
|
|
if (now > target) {
|
|
target.setDate(target.getDate() + 1);
|
|
}
|
|
const delay = target - now;
|
|
|
|
console.log(`⏰ Scheduler loaded. Next run in ${Math.floor(delay / 1000 / 60)} minutes.`);
|
|
setTimeout(async () => {
|
|
await runAutoClean();
|
|
// 실행 후 다음날 자정으로 다시 예약
|
|
startScheduler();
|
|
}, delay);
|
|
}
|
|
|
|
module.exports = {
|
|
start: startScheduler,
|
|
runNow: runAutoClean
|
|
};
|