使用Discord.js+MongoDB开发定时器命令遇BSONTypeError求助
问题:Agenda执行任务时触发BSON BigInt不支持错误
我使用Discord.js、MongoDB(mongoose封装)和Agenda开发定时器命令,功能是在指定时间后自动从数据库删除定时器。Bot就绪后会遍历数据库中的定时器,根据时间判断执行或推迟Agenda任务。但执行agenda.now<RemoveTimer>后代码停止运行,Agenda定义的任务从未执行,且出现报错:BSONTypeError: Unsupported type BigInt, please use Decimal128。
相关代码片段
遍历定时器并触发Agenda任务
// models.timer为mongoose的Model实例 const timers = await models.timer.find(); for (const timer of timers) { if (Date.now() > timer.endsAt) { console.log(Date.now(), timer.endsAt, timer.id); // 此日志正常输出 await agenda.now<RemoveTimer>(AgendaJobs.RemoveTimer, { timerId: timer.id, client: this.container.client, }); console.log("done"); // 从未输出 } }
Agenda任务定义
agenda.define<RemoveTimer>( AgendaJobs.RemoveTimer, async (job: Job<RemoveTimer>) => { console.log("job"); // 从未输出 // ... 任务逻辑 } );
Mongoose Timer Schema
const schema = new Schema<ITimer>({ name: { type: String, default: "Timer", }, createdBy: String, channelId: String, endsAt: Number, dm: { type: Boolean, default: false, }, }); export const TimerModel = model<ITimer>("timer", schema);
完整报错信息
2024-08-07 19:58:26 - ERROR - Encountered error on event listener "ready" for event "ready" at path "H:\GitStuff\nightmare-utils\dist\listeners\ready.js" BSONTypeError: Unsupported type BigInt, please use Decimal128 2024-08-07 19:58:26 - ERROR - at new BSONTypeError (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\error.js:41:28) 2024-08-07 19:58:26 - ERROR - at serializeInto (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:788:35) 2024-08-07 19:58:26 - ERROR - at serializeObject (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:282:20) 2024-08-07 19:58:26 - ERROR - at serializeInto (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:813:25) 2024-08-07 19:58:26 - ERROR - at serializeObject (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:282:20) 2024-08-07 19:58:26 - ERROR - at serializeInto (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:813:25) 2024-08-07 19:58:26 - ERROR - at serializeObject (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:282:20) 2024-08-07 19:58:26 - ERROR - at serializeInto (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:813:25) 2024-08-07 19:58:26 - ERROR - at serializeObject (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:282:20) 2024-08-07 19:58:26 - ERROR - at serializeInto (H:\GitStuff\nightmare-utils\node_modules\mongodb\node_modules\bson\lib\parser\serializer.js:607:25) { 2024-08-07 19:58:26 - ERROR - originalLine: 45, 2024-08-07 19:58:26 - ERROR - originalColumn: 30 2024-08-07 19:58:26 - ERROR - }
解决方案
核心原因
传给Agenda任务的client参数是Discord.js的Client实例,其中包含大量BigInt类型的字段(比如各种ID),而Agenda会将任务参数序列化为BSON存储到MongoDB中,BSON不支持直接序列化BigInt类型,导致序列化失败,代码中断,因此后续的日志和任务都无法执行。
修复步骤
- 避免传递复杂对象:不要将整个Discord.js Client实例传给Agenda任务,任务中如果需要使用Client,可以直接引用全局的Bot实例,无需通过参数传递。
- 转换BigInt为字符串:如果需要传递ID类参数(比如
timer.id),将BigInt类型转换为字符串,Discord.js完全支持用字符串ID进行操作:await agenda.now<RemoveTimer>(AgendaJobs.RemoveTimer, { timerId: String(timer.id), // 将BigInt转为字符串 // 移除client参数 }); - 精简任务参数:只传递任务执行必需的最小化参数(比如需要发送消息的话,只传channelId、userId等字符串类型参数),不要传递包含复杂类型的对象。
验证修改
修改后,Agenda任务参数可以正常序列化为BSON,代码会继续执行到"done"日志,Agenda的任务也会正常触发执行。
内容的提问来源于stack exchange,提问作者mallusr greatv2
相关产品推荐
相关产品推荐

