setInterval执行过期OTP记录删除任务时出现无限循环问题
定时任务每三个月删除过期OTP记录却陷入无限循环的问题解决
问题场景
需求为每三个月自动删除所有已过期的OTP记录,实现代码如下,但实际运行时函数频繁执行,日志疯狂输出,陷入无限循环。
代码实现
/sheduled-tasks/OTPRecords.js
const prisma = require("../services/prisma"); const THREE_MONTHS = 1000 * 60 * 60 * 24 * 90; async function deleteExpiredOTPRecords() { console.log("first"); setInterval(async () => { console.log("INTERVAL", THREE_MONTHS); const today = new Date(); const yesterday = new Date(today.setDate(today.getDate() - 1)); const records = await prisma.otp.deleteMany({ where: { expires_at: { lte: yesterday } }, }); console.log(records); }, THREE_MONTHS); } module.exports = deleteExpiredOTPRecords;
/index.js
deleteExpiredOTPRecords();
执行输出
INTERVAL 7776000000 INTERVAL 7776000000 { count: 0 } { count: 0 } INTERVAL 7776000000 { count: 0 } ...(重复输出) ^C(node:33075) [DEP0164] DeprecationWarning: Implicit coercion to integer for exit code is deprecated.
问题根因
JavaScript的setInterval(及setTimeout)接受的延迟参数是32位有符号整数,最大值为2147483647毫秒(约24.8天)。你的THREE_MONTHS计算值为7776000000毫秒,远超过该最大值,会被自动截断为负数。而setInterval对负数延迟的处理逻辑是立即执行回调,之后以近似0毫秒的间隔重复触发,最终导致函数疯狂执行。
另外原代码中日期处理存在隐性bug:today.setDate()会直接修改today本身,导致today和yesterday指向同一个日期对象。
修复方案
改用嵌套setTimeout实现超长期定时任务,每次任务执行完成后再设置下一次延迟,同时修正日期处理逻辑:
修改/sheduled-tasks/OTPRecords.js代码:
const prisma = require("../services/prisma"); const THREE_MONTHS = 1000 * 60 * 60 * 24 * 90; async function deleteExpiredOTPRecords() { console.log("Initializing OTP cleanup task"); // 封装任务执行逻辑 async function runCleanup() { console.log("Running OTP expired records cleanup"); const today = new Date(); // 先复制日期对象再修改,避免污染原变量 const yesterday = new Date(today); yesterday.setDate(today.getDate() - 1); const deleteResult = await prisma.otp.deleteMany({ where: { expires_at: { lte: yesterday } }, }); console.log("Cleanup completed, deleted records count:", deleteResult.count); // 任务完成后,设置下一次执行的延迟 setTimeout(runCleanup, THREE_MONTHS); } // 首次执行任务 runCleanup(); } module.exports = deleteExpiredOTPRecords;
额外建议
对于超长时间的定时任务,若服务重启会导致任务丢失,生产环境更推荐使用专门的任务调度工具(如node-schedule、Agenda)或系统级cron任务来实现,可靠性更高。
内容的提问来源于stack exchange,提问作者Shahed
相关产品推荐
相关产品推荐

