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

升级Sidekiq至7.x与Rails7后执行perform_later遇ActiveSupport::Duration错误

Sidekiq 7.x 下调用 perform_later 触发 ActiveSupport::Duration 错误问题

问题背景

  • 升级栈:从 Rails 5.2 + Ruby 2.6 升级至 Rails 7.0.4.2 + Ruby 2.7.7
  • 故障现象:调用任意 perform_later 都会抛出 ActiveSupport::Duration 相关错误
  • 环境对比:Rails 7.x + Ruby 2.7 + Sidekiq 6.x 可正常运行,仅升级到 Sidekiq 7.0.6 时出现故障,推测为 API 变更导致,但未定位具体原因
  • 依赖版本:Redis 5.0.6

排查与解决方向

1. 核对 Sidekiq 7.x 延迟任务参数处理逻辑

Sidekiq 7.x 对 ActiveJob perform_later 的参数序列化规则有调整,尤其是针对 ActiveSupport::Duration 的处理。避免直接传递 Duration 对象作为任务参数,或在设置延迟时使用不兼容的写法:

  • 错误示例:SomeJob.perform_later(1.hour)(将 Duration 作为任务参数)
  • 正确写法:若需设置延迟,使用 set(wait: 1.hour).perform_later(...);若需传递时间参数,转为数值(如 1.hour.to_i)或字符串(如 1.hour.to_s)后再传递。

2. 验证序列化兼容性

在 Rails 控制台中测试 Rails 和 Sidekiq 对 Duration 的序列化结果是否一致:

# 测试 Rails JSON 序列化
ActiveSupport::JSON.encode(1.hour)
# 测试 Sidekiq 序列化
Sidekiq.dump_json(1.hour)

若两者输出格式不同,可在 config/initializers/sidekiq.rb 中配置统一的序列化方式,或手动对 Duration 进行转换后再传入任务。

3. 检查 Job 定义的参数解析

确认所有 Sidekiq Job 的 perform 方法参数是否能正确处理序列化后的数值/字符串。Sidekiq 7 严格限制了可序列化参数类型,若 Job 直接依赖 Duration 对象,需改为接收数值后再转换为 Duration:

# 调整前
def perform(duration)
  # 使用 duration(Duration 对象)
end

# 调整后
def perform(seconds)
  duration = ActiveSupport::Duration.build(seconds)
  # 使用 duration
end

4. 查阅 Sidekiq 7 升级日志

重点关注 Sidekiq 7.0.x 版本中关于 ActiveJob 集成、参数序列化的 breaking change,尤其是与 Rails 7 兼容性相关的条目,可能存在未被注意到的行为变更。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:47:07