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

Devise仅为服务器重启后首个用户发送确认邮件问题求助

解决Devise邮件deliver_later触发ActiveJob::DeserializationError的问题

问题根源

注册流程中,Devise默认在用户创建的数据库事务内触发邮件通知,而deliver_later会立即将Job推入Sidekiq队列。如果Sidekiq在事务提交前就执行Job,此时数据库还未持久化新用户记录,就会抛出ActiveJob::DeserializationError(找不到对应ID的用户)。首个用户能收到邮件,通常是因为服务器重启后Sidekiq初始化有延迟,事务已完成提交才执行Job;后续用户由于Sidekiq处理速度快,事务未提交就执行Job,导致报错。

解决方案

1. 修改send_devise_notification方法,延迟到事务提交后发送邮件

在User模型中重写方法,判断当前是否处于事务中,若是则通过after_commit回调延迟发送:

def send_devise_notification(notification, *args)
  # 检查是否存在未提交的数据库事务
  if self.class.connection.open_transactions > 0
    # 根据用户是否已持久化,选择对应的回调时机
    callback_type = self.persisted? ? :update : :create
    after_commit -> {
      devise_mailer.send(notification, self, *args).deliver_later
    }, on: callback_type
  else
    # 无事务直接发送
    devise_mailer.send(notification, self, *args).deliver_later
  end
end

2. 验证Sidekiq队列配置

确保application.rb中ActiveJob适配器配置正确:

config.active_job.queue_adapter = :sidekiq

同时检查Sidekiq的队列优先级,避免邮件Job被优先执行导致事务未提交。

3. 排除其他可能原因

  • 确认用户模型主键是否为整数(若使用UUID,需确保ActiveJob支持UUID反序列化,但此问题中首个用户正常,大概率不是此原因);
  • 检查注册流程中是否有异常逻辑(如创建用户后立即修改/删除记录);
  • 完全禁用devise-async相关配置,避免与自定义的send_devise_notification方法冲突。

内容的提问来源于stack exchange,提问作者Tomasz Jóźwik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:47:16