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
相关产品推荐
相关产品推荐

