diff --git a/.github/workflows/redis-keepalive.yml b/.github/workflows/redis-keepalive.yml new file mode 100644 index 0000000..5245821 --- /dev/null +++ b/.github/workflows/redis-keepalive.yml @@ -0,0 +1,15 @@ +name: redis-keepalive + +on: + schedule: + - cron: '0 3 * * 1' # 매주 월요일 03:00 UTC (12:00 KST) + workflow_dispatch: + +jobs: + ping: + runs-on: ubuntu-latest + steps: + - name: Ping dev Redis via /health/redis + run: curl -fsS -m 10 https://promptplace-dev.kro.kr/health/redis + - name: Ping prod Redis via /health/redis + run: curl -fsS -m 10 https://promptplace.kro.kr/health/redis diff --git a/src/index.ts b/src/index.ts index 6b8ba55..5a6c4dd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import { errorHandler } from "./middlewares/errorHandler"; import { visitorTracker } from "./middlewares/visitorTracker"; import "reflect-metadata"; import passport from "./config/passport"; +import redisClient from "./config/redis"; import swaggerUi from "swagger-ui-express"; import swaggerJsdoc from "swagger-jsdoc"; import { swaggerOptions } from "./docs/swagger/options"; @@ -210,7 +211,22 @@ app.use(errorHandler as ErrorRequestHandler); // 도커 헬스체크 라우터 app.get('/health', (req, res) => { - res.status(200).send('OK'); + res.status(200).send('OK'); +}); + +// ponytail: Upstash free 유휴 자동 삭제 방지용. 외부 cron 이 주기적으로 호출. +app.get('/health/redis', async (_req, res) => { + try { + const pong = await Promise.race([ + redisClient.ping(), + new Promise((_, reject) => + setTimeout(() => reject(new Error('timeout')), 2000), + ), + ]); + res.status(200).send(pong); + } catch { + res.status(503).send('REDIS_UNAVAILABLE'); + } }); app.use(morgan('dev')); // 사용자 요청 로그 출력