用途:用于 Rails 后台任务的设计与评审,整理自 Campfire(Resque,4 个薄任务)与 Fizzy(Solid Queue,多队列)的实践。
主要能力与默认做法:任务保持浅层,perform 只调用一行模型方法,如 def perform(card) = card.notify_recipients;任务需幂等、可安全重试(例如在领域操作中 rescue RecordNotUnique);真实错误要显式失败,避免静默 rescue;在应用默认中设置 ActiveJob::Base.enqueue_after_transaction_commit = true,从根源修复数据未提交就入队的竞态;新应用优先用数据库支持的 Solid Queue 而非 Redis 队列,小规模部署可与 Puma 同机(SOLID_QUEUE_IN_PUMA)。
命名与上下文:_later 负责入队,普通名执行工作,_now 为显式同步版本;入队时上下文用关键字参数捕获,如 Mention::CreateJob.perform_later(self, mentioner: Current.user),不要在 perform 时依赖 Current;多租户应用需把租户上下文序列化进每个任务,在入队时以 GlobalID 捕获 Current.account,并在 Current.with_account 中包裹 perform_now。
良好模式:任务负载要小,传记录(GlobalID)或 ID;按重要性拆分队列并显式设定优先级;编排任务与重处理任务分离;周期性任务错开在奇数分钟(12、27、50);批量入队用 due.in_batches { |batch| ActiveJob.perform_all_later(batch.map { DeliverJob.new(it) }) };长迭代用 ActiveJob::Continuable 的 step、find_each(start: step.cursor)、step.advance! 保证崩溃安全;用 limits_concurrency to: 1, key: ->(owner) { owner } 串行化同一属主的工作;高扇出 HTTP 用两级异步;after_destroy_commit 的异步工作需在 before_destroy 快照关联。
周期与维护:周期任务调用普通模型类方法(command: "MagicLink.cleanup"),不用专门任务类;保留清理用作用域上的 delete_all;为已完成队列任务、过期令牌、旧投递记录安排清理;优先用使用时重置而非 cron 重置;在 beta/staging 精简周期计划。
错误处理:瞬时失败用 retry_on ..., wait: :polynomially_longer;永久失败不重试,按错误类/消息分类并以 :info 记录后继续;区分“目标失败”与“自身代码异常”;错误分类可打包为 concern 并 include 进框架任务。
测试:不为琐碎任务类写单元测试,改在模型测试中用 perform_enqueued_jobs(only: Mention::CreateJob) 与 assert_enqueued_with 验证异步行为,断言可观察结果而非任务内部。
限制与警示:避免任务内嵌复杂分支与业务规则、无保护的非幂等副作用、重试永久无效输入、记录未提交就入队、perform 中直接读 Current、循环内逐条 perform_later、用 cron 重置替代使用时重置,以及后台任务触发多余 Turbo 广播(可用 suppressing_turbo_broadcasts 包裹)。