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

Wisper发布时出现ActiveRecordNotFound错误的原因排查

问题:发布:message_created事件后订阅者报ActiveRecordNotFound错误

我们有ChatRoom模型和Message模型,两者是一对多关联。ChatRoom中实现了add_message方法,用于创建消息,同时接收布尔型参数notify来控制是否为新创建的消息发送邮件。创建消息后会发布:message_created事件,但订阅者执行时会抛出Couldn't find Message with 'id'=xxx错误——明明对应的消息ID存在,且消息已经持久化到数据库。

相关代码

ChatRoom模型代码

class ChatRoom < ApplicationRecord
  has_many :messages, -> { order(:created_at) }

  def add_message(args)
    content = args.fetch(:content)
    creator = args.fetch(:creator)
    notify = args.fetch(:notify, false)

    message = self.messages.create!(content: content, creator: creator)
    publish(:message_created, message_id: message.id, notify: notify)
  end
end

事件订阅者代码

class MessageCreated::MailChatSubscriber < ApplicationSubscriber
  def message_created(args)
    message = Message.find(args.fetch(:message_id))
    notify = args.fetch(:notify)

    Messages::Organizers::SendChatResponseMail.call(
      message: message,
      notify: notify
    )
  end
end

错误信息

Couldn't find Message with 'id'=575565

问题成因

核心原因是数据库事务的延迟可见性:

  • 如果add_message方法是在一个未提交的外层数据库事务中被调用的(比如控制器动作、上层服务类开启了事务),哪怕create!已经生成了消息ID并写入数据库,只要外层事务没提交,这条消息的数据变更就处于未提交状态。
  • 事件订阅者如果是异步执行的(比如用Sidekiq等后台队列处理),会在独立线程中查询数据库,此时无法读取到未提交事务中的数据,就会触发ActiveRecordNotFound错误。
  • 哪怕create!本身是立即提交的小事务,只要外层存在未提交的大事务,这条消息的变更依然对其他线程不可见。

修复方案

方案一:在事务提交后发布事件

利用Rails的after_commit回调,确保事件在消息的事务完全提交后再发布。修改add_message方法:

def add_message(args)
  content = args.fetch(:content)
  creator = args.fetch(:creator)
  notify = args.fetch(:notify, false)

  message = self.messages.create!(content: content, creator: creator)
  # 等待事务提交后再发布事件
  message.run_after_commit do
    publish(:message_created, message_id: message.id, notify: notify)
  end
end

方案二:确保事件订阅同步执行(仅适合特定场景)

如果业务允许事件订阅同步执行(即发布事件后立即在当前线程处理),那么不会出现事务可见性问题,但这种方式可能影响主请求的响应速度,仅适合轻量级处理逻辑。

内容的提问来源于stack exchange,提问作者Brandon Teixeira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:54:23