cron 스케줄러 한국 시간대 적용 및 봇 카드 UI 개선

- scheduler.js: cron.schedule에 timezone: 'Asia/Seoul' 옵션 추가
- bots.js: Meilisearch 봇 API에 버전 정보 추가
- BotCard.jsx: Meilisearch 봇 카드에 마지막 동기화 시간, 동기화 수, 버전 표시

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-01-23 21:52:01 +09:00
parent 8091f4ac67
commit 95285634e9
3 changed files with 37 additions and 14 deletions

View file

@ -4,6 +4,7 @@ import bots from '../config/bots.js';
import { syncWithRetry, getVersion } from '../services/meilisearch/index.js';
const REDIS_PREFIX = 'bot:status:';
const TIMEZONE = 'Asia/Seoul';
async function schedulerPlugin(fastify, opts) {
const tasks = new Map();
@ -60,7 +61,7 @@ async function schedulerPlugin(fastify, opts) {
const CHECK_INTERVAL = 60 * 1000; // 1분
const CHECK_DURATION = 5 * 60 * 1000; // 5분간 체크
// 체크 시작 cron (매일 4시)
// 체크 시작 cron (매일 4시 KST)
const task = cron.schedule(bot.cron, async () => {
fastify.log.info(`[${botId}] 버전 체크 시작 (5분간 1분 간격)`);
await updateStatus(botId, { status: 'running' });
@ -114,7 +115,7 @@ async function schedulerPlugin(fastify, opts) {
await performSync(botId, currentVersion, REDIS_VERSION_KEY);
}
}, CHECK_INTERVAL);
});
}, { timezone: TIMEZONE });
tasks.set(botId, task);
await updateStatus(botId, { status: 'running' });
@ -202,7 +203,7 @@ async function schedulerPlugin(fastify, opts) {
throw new Error(`지원하지 않는 봇 타입: ${bot.type}`);
}
// cron 태스크 등록
// cron 태스크 등록 (한국 시간 기준)
const task = cron.schedule(bot.cron, async () => {
fastify.log.info(`[${botId}] 동기화 시작`);
try {
@ -217,7 +218,7 @@ async function schedulerPlugin(fastify, opts) {
});
fastify.log.error(`[${botId}] 동기화 오류: ${err.message}`);
}
});
}, { timezone: TIMEZONE });
tasks.set(botId, task);
await updateStatus(botId, { status: 'running' });

View file

@ -67,7 +67,7 @@ export default async function botsRoutes(fastify) {
checkInterval = parseInt(cronMatch[1]);
}
result.push({
const botData = {
id: bot.id,
name: bot.name || bot.channelName || bot.username || bot.id,
type: bot.type,
@ -78,7 +78,15 @@ export default async function botsRoutes(fastify) {
check_interval: checkInterval,
error_message: status.errorMessage,
enabled: bot.enabled,
});
};
// Meilisearch 봇인 경우 버전 정보 추가
if (bot.type === 'meilisearch') {
const version = await redis.get('meilisearch:version');
botData.version = version || '-';
}
result.push(botData);
}
return result;

View file

@ -145,14 +145,28 @@ const BotCard = memo(function BotCard({
{bot.type === 'meilisearch' ? (
<>
<div className="p-3 text-center">
<div className="text-lg font-bold text-gray-900">{bot.schedules_added || 0}</div>
<div className="text-xs text-gray-400">동기화 </div>
<div className="text-lg font-bold text-gray-900">
{bot.last_check_at
? new Date(bot.last_check_at).toLocaleString('ko-KR', {
month: 'numeric',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
hour12: false,
})
: '-'}
</div>
<div className="text-xs text-gray-400">마지막 동기화</div>
</div>
<div className="p-3 text-center">
<div className="text-lg font-bold text-gray-900">
{bot.last_added_count ? `${(bot.last_added_count / 1000 || 0).toFixed(1)}` : '-'}
{bot.last_added_count?.toLocaleString() || '-'}
</div>
<div className="text-xs text-gray-400">소요 시간</div>
<div className="text-xs text-gray-400">동기화 </div>
</div>
<div className="p-3 text-center">
<div className="text-lg font-bold text-gray-900">{bot.version || '-'}</div>
<div className="text-xs text-gray-400">버전</div>
</div>
</>
) : (
@ -169,12 +183,12 @@ const BotCard = memo(function BotCard({
</div>
<div className="text-xs text-gray-400">마지막</div>
</div>
</>
)}
<div className="p-3 text-center">
<div className="text-lg font-bold text-gray-900">{formatInterval(bot.check_interval)}</div>
<div className="text-xs text-gray-400">업데이트 간격</div>
</div>
</>
)}
</div>
{/* 오류 메시지 */}