You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AdonisJs中socket.io在adonis5-scheduler任务内调用emit失效

AdonisJs 集成socket.io在定时任务中失效修复

问题原因

出现「控制器中Ws.io.emit正常、定时任务中emit不生效但日志正常打印」的现象,核心是两个逻辑问题:

  • Ws服务的初始化逻辑没有绑定到应用全局启动生命周期,仅在HTTP请求链路(控制器、路由处理逻辑)中被触发执行。定时任务独立于HTTP请求生命周期运行,任务触发时Ws.io实例要么未初始化,要么没有绑定到正在监听端口的AdonisServer实例上。
  • 默认配置下adonis5-scheduler会在独立子进程中执行任务,子进程与主HTTP进程内存空间隔离,子进程中拿到的Ws实例和主进程对外提供服务的socket.io实例不是同一个,无法向已连接的客户端推送消息。

修复步骤

  1. 全局启动阶段初始化Ws服务
    不要等HTTP请求触发才调用Ws.boot(),将初始化逻辑放到应用全局启动的ready钩子里,确保服务启动时Ws实例就完成挂载。
    修改providers/AppProvider.ts文件,加入Ws初始化逻辑:
// 替换成你项目中Ws模块的实际引入路径
import Ws from 'App/Services/Ws'

export default class AppProvider {
  public async ready() {
    Ws.boot()
  }
}
  1. 关闭定时任务的子进程运行模式
    在项目配置目录下新建/修改config/scheduler.ts,关闭worker进程模式,让定时任务和主HTTP服务运行在同一进程,共享内存中的Ws实例:
export default {
  runInWorker: false,
  path: 'app/Tasks' // 保持和你实际存放定时任务的目录路径一致
}
  1. 增加实例存在性校验
    在定时任务的handle方法中增加兜底校验,避免极端场景下实例未初始化导致静默失败:
import { BaseTask } from 'adonis5-scheduler/build'
// 替换成你项目中Ws模块的实际引入路径
import Ws from 'App/Services/Ws'

export default class GetRouletteGame extends BaseTask {
    public static get schedule() {
        return '*/3 * * * * *'
    }
    public static get useLock() {
        return false
    }

    public async handle() {
      if (!Ws.io) {
        Ws.boot()
      }
      Ws.io.emit(`taskName`, 1)
      console.log('ok')
    }
}

注意点

你当前的Ws模块实现不需要额外调用io.listen(),因为已经传入了已启动的AdonisServer实例,重复监听端口反而会导致端口占用报错。

内容的提问来源于stack exchange,提问作者marcelo.delta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:06:26