Browse Source

Add a circuit breaker for ActivityPub deliveries (#7053)

Eugen Rochko 6 years ago
parent
commit
d4de2239b0
4 changed files with 16 additions and 5 deletions
  1. 2 0
      Gemfile
  2. 2 0
      Gemfile.lock
  3. 9 5
      app/workers/activitypub/delivery_worker.rb
  4. 3 0
      config/initializers/stoplight.rb

+ 2 - 0
Gemfile

@@ -35,6 +35,7 @@ gem 'devise-two-factor', '~> 3.0'
 group :pam_authentication, optional: true do
   gem 'devise_pam_authenticatable2', '~> 9.0'
 end
+
 gem 'net-ldap', '~> 0.10'
 gem 'omniauth-cas', '~> 1.1'
 gem 'omniauth-saml', '~> 1.10'
@@ -79,6 +80,7 @@ gem 'sidekiq-bulk', '~>0.1.1'
 gem 'simple-navigation', '~> 4.0'
 gem 'simple_form', '~> 3.4'
 gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
+gem 'stoplight', '~> 2.1.3'
 gem 'strong_migrations'
 gem 'tty-command'
 gem 'tty-prompt'

+ 2 - 0
Gemfile.lock

@@ -550,6 +550,7 @@ GEM
       net-scp (>= 1.1.2)
       net-ssh (>= 2.8.0)
     statsd-ruby (1.2.1)
+    stoplight (2.1.3)
     streamio-ffmpeg (3.0.2)
       multi_json (~> 1.8)
     strong_migrations (0.1.9)
@@ -716,6 +717,7 @@ DEPENDENCIES
   simple_form (~> 3.4)
   simplecov (~> 0.14)
   sprockets-rails (~> 3.2)
+  stoplight (~> 2.1.3)
   streamio-ffmpeg (~> 3.0)
   strong_migrations
   tty-command

+ 9 - 5
app/workers/activitypub/delivery_worker.rb

@@ -12,9 +12,7 @@ class ActivityPub::DeliveryWorker
     @source_account = Account.find(source_account_id)
     @inbox_url      = inbox_url
 
-    perform_request do |response|
-      raise Mastodon::UnexpectedResponseError, response unless response_successful? response
-    end
+    perform_request
 
     failure_tracker.track_success!
   rescue => e
@@ -30,8 +28,14 @@ class ActivityPub::DeliveryWorker
     request.add_headers(HEADERS)
   end
 
-  def perform_request(&block)
-    build_request.perform(&block)
+  def perform_request
+    light = Stoplight(@inbox_url) do
+      build_request.perform do |response|
+        raise Mastodon::UnexpectedResponseError, response unless response_successful?(response)
+      end
+    end
+
+    light.run
   end
 
   def response_successful?(response)

+ 3 - 0
config/initializers/stoplight.rb

@@ -0,0 +1,3 @@
+require 'stoplight'
+
+Stoplight::Light.default_data_store = Stoplight::DataStore::Redis.new(Redis.current)