초기 PM 소스 전체 업로드

This commit is contained in:
koj729
2026-06-12 17:14:03 +09:00
commit 4e33c9a02a
1769 changed files with 377797 additions and 0 deletions

118
libs/scheduler.js Normal file
View File

@@ -0,0 +1,118 @@
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
};