reports: increase database timeout; add rate limits.
Increase the database timeout to 10 seconds when generating reports. Generating reports tends to be slow, especially for things like graphing posts over time since the beginning of Danbooru. Does not apply to anonymous users. Users must have an account to get higher timeouts so that we can identify users scraping reports too hard. Also add a rate limit of 1 report per 3 seconds to limit abuse.
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
class ReportsController < ApplicationController
|
class ReportsController < ApplicationController
|
||||||
respond_to :html, :json, :xml
|
respond_to :html, :json, :xml
|
||||||
|
|
||||||
|
rate_limit :show, rate: 1.0/3.seconds, burst: 15
|
||||||
|
|
||||||
def index
|
def index
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -75,7 +77,16 @@ class ReportsController < ApplicationController
|
|||||||
@from = params.dig(:search, :from) || 1.month.ago
|
@from = params.dig(:search, :from) || 1.month.ago
|
||||||
@to = params.dig(:search, :to) || Time.zone.now
|
@to = params.dig(:search, :to) || Time.zone.now
|
||||||
|
|
||||||
@results = @model.search(params[:search], CurrentUser.user).timeseries(period: @period, from: @from, to: @to, columns: @columns)
|
if CurrentUser.user.is_member? && CurrentUser.user.statement_timeout < 10_000
|
||||||
|
@statement_timeout = 10_000
|
||||||
|
else
|
||||||
|
@statement_timeout = CurrentUser.user.statement_timeout
|
||||||
|
end
|
||||||
|
|
||||||
|
ApplicationRecord.set_timeout(@statement_timeout) do
|
||||||
|
@results = @model.search(params[:search], CurrentUser.user).timeseries(period: @period, from: @from, to: @to, columns: @columns)
|
||||||
|
end
|
||||||
|
|
||||||
respond_with(@results)
|
respond_with(@results)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -134,6 +134,13 @@ class ApplicationRecord < ActiveRecord::Base
|
|||||||
|
|
||||||
concerning :ActiveRecordExtensions do
|
concerning :ActiveRecordExtensions do
|
||||||
class_methods do
|
class_methods do
|
||||||
|
def set_timeout(n)
|
||||||
|
connection.execute("SET STATEMENT_TIMEOUT = #{n}") unless Rails.env.test?
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
connection.execute("SET STATEMENT_TIMEOUT = #{CurrentUser.user.statement_timeout}") unless Rails.env.test?
|
||||||
|
end
|
||||||
|
|
||||||
def without_timeout
|
def without_timeout
|
||||||
connection.execute("SET STATEMENT_TIMEOUT = 0") unless Rails.env.test?
|
connection.execute("SET STATEMENT_TIMEOUT = 0") unless Rails.env.test?
|
||||||
yield
|
yield
|
||||||
|
|||||||
Reference in New Issue
Block a user