我们都曾遇到过希望在生产环境中禁用或取消出问题的 Sidekiq 任务的情况。当前的解决方案通常涉及清空特定任务的队列或向生产环境部署热修复来禁用任务。虽然这些方法在初期可以解决问题,但随着你的应用成长、任务队列变得复杂,你会希望有一个更健壮且近乎即时的解决方案。
在本文中,我们将介绍如何构建一个 Sidekiq 客户端中间件,在生产环境中终止 Sidekiq 任务,而无需依赖部署。


Sidekiq 客户端中间件

在 PlanetScale 中,我们目前使用非常优秀的 flipper gem 来为正在构建的新功能增加功能开关(feature flag)。Flipper 的一个主要优点是,它允许我们在生产环境中启用/禁用不同的代码路径,而无需进行部署。基于这一点,我们决定使用其功能开关的能力来帮助我们在生产环境中禁用任务。
我们创建了一个中间件文件 lib/sidekiq_middleware/sidekiq_jobs_flipper.rb,如下所示:

module SidekiqMiddleware
  class SidekiqJobsFlipper
    def call(worker_class, job, queue, redis_pool)
      # 返回 false 或 nil 以阻止任务被推送至 Redis
      klass = worker_class.to_s
      if Flipper.enabled?("disable_#{klass.underscore.to_sym}")
        return false
      end

      yield
    end
  end
end

Sidekiq 客户端中间件在将任务推送到 Redis 时运行。以下是中间件中的关键代码,使用它可以终止被功能开关标记为禁用的任务:

if Flipper.enabled?("disable_#{klass.underscore.to_sym}")
  return false
end

使用示例

如果你希望在自己的应用中禁用生产环境中的任务,可以使用这个中间件。

1. 创建中间件文件

新建一个中间件文件,并将上述代码粘贴进去。

2. 在 Sidekiq 配置中添加中间件

config/initializers/sidekiq.rb 文件中添加中间件:

Sidekiq.configure_server do |config|
  config.client_middleware do |chain|
    chain.add(SidekiqMiddleware::SidekiqJobsFlipper)
  end
end

3. 禁用任务

在生产环境中禁用任务时,只需将任务类名转化为小写并添加前缀 disable_。以下以 InvoiceJob 为例:

class InvoiceJob
  include Sidekiq::Worker

  def perform(...)
    ...
  end
end

在这种情况下,类名 InvoiceJob 变为 disable_invoice_job
要禁用 InvoiceJob,运行以下命令:

Flipper.enable("disable_invoice_job")


如何在 Ruby on Rails 中终止 Sidekiq 任务插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.choupangxia.com/2025/09/07/ruby-on-rails-sidekiq-task/