about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/workers/pubsubhubbub/subscribe_worker.rb2
-rw-r--r--config/application.rb1
-rw-r--r--config/initializers/sidekiq.rb3
-rw-r--r--lib/mastodon/unique_retry_job_middleware.rb20
4 files changed, 25 insertions, 1 deletions
diff --git a/app/workers/pubsubhubbub/subscribe_worker.rb b/app/workers/pubsubhubbub/subscribe_worker.rb
index 7560c2671..130c967e0 100644
--- a/app/workers/pubsubhubbub/subscribe_worker.rb
+++ b/app/workers/pubsubhubbub/subscribe_worker.rb
@@ -3,7 +3,7 @@
 class Pubsubhubbub::SubscribeWorker
   include Sidekiq::Worker
 
-  sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false
+  sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false, unique_retry: true
 
   sidekiq_retry_in do |count|
     case count
diff --git a/config/application.rb b/config/application.rb
index b6ce74147..f98f7af16 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -10,6 +10,7 @@ require_relative '../app/lib/exceptions'
 require_relative '../lib/paperclip/gif_transcoder'
 require_relative '../lib/paperclip/video_transcoder'
 require_relative '../lib/mastodon/version'
+require_relative '../lib/mastodon/unique_retry_job_middleware'
 
 Dotenv::Railtie.load
 
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index b70784d79..61e131336 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -13,4 +13,7 @@ end
 
 Sidekiq.configure_client do |config|
   config.redis = redis_params
+  config.client_middleware do |chain|
+    chain.add Mastodon::UniqueRetryJobMiddleware
+  end
 end
diff --git a/lib/mastodon/unique_retry_job_middleware.rb b/lib/mastodon/unique_retry_job_middleware.rb
new file mode 100644
index 000000000..75da8a0c9
--- /dev/null
+++ b/lib/mastodon/unique_retry_job_middleware.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class Mastodon::UniqueRetryJobMiddleware
+  def call(_worker_class, item, _queue, _redis_pool)
+    return if item['unique_retry'] && retried?(item)
+    yield
+  end
+
+  private
+
+  def retried?(item)
+    # Use unique digest key of SidekiqUniqueJobs
+    unique_key = SidekiqUniqueJobs::UNIQUE_DIGEST_KEY
+    unique_digest = item[unique_key]
+    class_name = item['class']
+    retries = Sidekiq::RetrySet.new
+
+    retries.any? { |job| job.item['class'] == class_name && job.item[unique_key] == unique_digest }
+  end
+end