Under load, multiple backups for a single user could be planned, which
is very expensive.
end
def create
- authorize :backup, :create?
+ raise Mastodon::NotPermittedError unless user_signed_in?
+
+ backup = nil
+
+ RedisLock.acquire(lock_options) do |lock|
+ if lock.acquired?
+ authorize :backup, :create?
+ backup = current_user.backups.create!
+ else
+ raise Mastodon::RaceConditionError
+ end
+ end
- backup = current_user.backups.create!
BackupWorker.perform_async(backup.id)
redirect_to settings_export_path
end
+
+ def lock_options
+ { redis: Redis.current, key: "backup:#{current_user.id}" }
+ end
end