Browse Source

Fix some RedisLocks auto-releasing too fast (#16276)

* Fix Delete and Create-related locks expiring too fast

Fixes #16238

By default, RedisLock expires after 10 seconds, which may not be enough to
process statuses, especially when those have attached media files.

This commit extends those 10 seconds to 15 minutes, which should be plenty
enough to handle any status, while being short enough to not waste many
sidekiq job retries in the exceedingly rare case in which a sidekiq process
would crash when processing a `Create` or `Delete`.

* Fix other RedisLock autorelease durations

Fixes #15645

- things that only perform a few simple database queries (e.g. finding and
  saving a record) have been left unchanged, so they'll still use the default
  10s duration
- things that perform significantly more complex database queries have been
  changed to a 5 minutes timeout
- things that perform multiple HTTP queries have been changed to a 15 minutes
  timeout
closed-social-v3
Claire 3 years ago
committed by GitHub
parent
commit
9a19227f17
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 7 additions and 7 deletions
  1. +2
    -2
      app/lib/activitypub/activity.rb
  2. +1
    -1
      app/services/activitypub/process_account_service.rb
  3. +1
    -1
      app/services/fetch_link_card_service.rb
  4. +1
    -1
      app/services/remove_status_service.rb
  5. +1
    -1
      app/services/resolve_account_service.rb
  6. +1
    -1
      app/workers/distribution_worker.rb

+ 2
- 2
app/lib/activitypub/activity.rb View File

@ -216,8 +216,8 @@ class ActivityPub::Activity
redis.del(key)
end
def lock_or_fail(key)
RedisLock.acquire({ redis: Redis.current, key: key }) do |lock|
def lock_or_fail(key, expire_after = 15.minutes.seconds)
RedisLock.acquire({ redis: Redis.current, key: key, autorelease: expire_after }) do |lock|
if lock.acquired?
yield
else

+ 1
- 1
app/services/activitypub/process_account_service.rb View File

@ -290,7 +290,7 @@ class ActivityPub::ProcessAccountService < BaseService
end
def lock_options
{ redis: Redis.current, key: "process_account:#{@uri}" }
{ redis: Redis.current, key: "process_account:#{@uri}", autorelease: 15.minutes.seconds }
end
def process_tags

+ 1
- 1
app/services/fetch_link_card_service.rb View File

@ -175,6 +175,6 @@ class FetchLinkCardService < BaseService
end
def lock_options
{ redis: Redis.current, key: "fetch:#{@url}" }
{ redis: Redis.current, key: "fetch:#{@url}", autorelease: 15.minutes.seconds }
end
end

+ 1
- 1
app/services/remove_status_service.rb View File

@ -141,6 +141,6 @@ class RemoveStatusService < BaseService
end
def lock_options
{ redis: Redis.current, key: "distribute:#{@status.id}" }
{ redis: Redis.current, key: "distribute:#{@status.id}", autorelease: 5.minutes.seconds }
end
end

+ 1
- 1
app/services/resolve_account_service.rb View File

@ -146,6 +146,6 @@ class ResolveAccountService < BaseService
end
def lock_options
{ redis: Redis.current, key: "resolve:#{@username}@#{@domain}" }
{ redis: Redis.current, key: "resolve:#{@username}@#{@domain}", autorelease: 15.minutes.seconds }
end
end

+ 1
- 1
app/workers/distribution_worker.rb View File

@ -4,7 +4,7 @@ class DistributionWorker
include Sidekiq::Worker
def perform(status_id)
RedisLock.acquire(redis: Redis.current, key: "distribute:#{status_id}") do |lock|
RedisLock.acquire(redis: Redis.current, key: "distribute:#{status_id}", autorelease: 5.minutes.seconds) do |lock|
if lock.acquired?
FanOutOnWriteService.new.call(Status.find(status_id))
else

Loading…
Cancel
Save