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

通过Sidekiq发送Devise确认邮件时遇用户映射及找不到用户问题

Devise + Sidekiq 发送确认邮件初期报错问题解决

问题描述

用户注册时,通过Sidekiq异步发送Devise确认邮件,初期持续出现Couldn't find User with 'id'=xxx错误(用户提到的"Could not find a valid mapping for User"为初期表象,实际日志显示记录未找到),但Sidekiq重试几分钟后邮件可正常发送。已按Devise文档重写send_devise_notification方法,尝试过after_commit触发仍未解决。

相关代码:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable  

  def send_devise_notification(notification, *args)
    devise_mailer.send(notification, self, *args).deliver_later
  end
end

报错日志:

2025-01-28T14:52:31.012Z pid=30324 tid=6kk class=ActionMailer::MailDeliveryJob jid=3aba9b7903de8de2e2a5905e elapsed=0.024 INFO: fail
2025-01-28T14:52:31.012Z pid=30324 tid=6kk WARN: {"context":"Job raised exception","job":{"retry":true,"queue":"default","wrapped":"ActionMailer::MailDeliveryJob","args":[{"job_class":"ActionMailer::MailDeliveryJob","job_id":"96a7d608-0233-4a79-a7d5-f4d1f3c64e18","provider_job_id":null,"queue_name":"default","priority":null,"arguments":["Devise::Mailer","confirmation_instructions","deliver_now",{"args":[{"_aj_globalid":"gid://lookn-for-group/User/33"},"A8enbvseX9GdGGuY5YG8",{"_aj_symbol_keys":[]}],"_aj_ruby2_keywords":["args"]}],"executions":0,"exception_executions":{},"locale":"en","timezone":"UTC","enqueued_at":"2025-01-28T14:41:47.395153390Z","scheduled_at":"2025-01-28T14:41:52.394533706Z"}],"class":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper","jid":"3aba9b7903de8de2e2a5905e","created_at":1738075307.395294,"enqueued_at":1738075950.9874232,"error_message":"Error while trying to deserialize arguments: Couldn't find User with 'id'=33","error_class":"ActiveJob::DeserializationError","failed_at":1738075312.8300993,"retry_count":4,"retried_at":1738075647.2435138}}
2025-01-28T14:52:31.012Z pid=30324 tid=6kk WARN: ActiveJob::DeserializationError: Error while trying to deserialize arguments: Couldn't find User with 'id'=33
2025-01-28T14:52:31.014Z pid=30324 tid=6kk WARN: 

解决方案

原因分析

报错核心是Sidekiq执行邮件任务时,用户记录尚未持久化到数据库,或数据未同步到Sidekiq连接的数据库节点:

  1. Devise注册流程在事务中执行,直接调用deliver_later会导致任务在事务提交前入队,Sidekiq执行时用户记录还不存在;
  2. 若使用数据库读写分离,Sidekiq连接从库时,新用户数据可能未完成主从同步。

方案1:确保事务提交后触发邮件任务

修改User模型的send_devise_notification方法,绑定到after_commit回调,仅在用户创建事务提交后异步发送邮件:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable  

  def send_devise_notification(notification, *args)
    # 针对确认邮件,仅在用户创建并提交事务后触发异步发送
    if persisted? && notification == :confirmation_instructions
      after_commit -> { devise_mailer.send(notification, self, *args).deliver_later }, on: :create, prepend: true
    else
      # 其他通知沿用默认处理逻辑
      super
    end
  end
end
  • on: :create:限定仅在用户创建操作的事务提交后执行;
  • prepend: true:确保该回调优先于其他可能的after_commit回调执行,避免被覆盖。

方案2:解决数据库读写分离同步延迟

若应用使用读写分离,配置Sidekiq强制连接主库,避免从库同步延迟问题:
在config/initializers/sidekiq.rb中添加以下配置:

Sidekiq.configure_server do |config|
  config.on(:startup) do
    # 让Sidekiq工作进程连接主库
    ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[Rails.env]["primary"])
  end
end
  • 注:若你的主库配置键不是primary,请替换为实际配置名(比如master)。

内容的提问来源于stack exchange,提问作者David Bista

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:50:13