Class: Gitlab::QueryLimiting::Transaction
- Inherits:
-
Object
- Object
- Gitlab::QueryLimiting::Transaction
- Defined in:
- lib/gitlab/query_limiting/transaction.rb
Constant Summary collapse
- THREAD_KEY =
:__gitlab_query_counts_transaction
- THRESHOLD =
The maximum number of SQL queries that can be executed in a request. For the sake of keeping things simple we hardcode this value here, it's not supposed to be changed very often anyway.
100
- LOG_THRESHOLD =
THRESHOLD * 1.5
- ThresholdExceededError =
Error that is raised whenever exceeding the maximum number of queries.
Class.new(StandardError)
- GEO_NODES_LOAD =
'SELECT 1 AS one FROM "geo_nodes" LIMIT 1'
- LICENSES_LOAD =
'SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id"'
Instance Attribute Summary collapse
-
#action ⇒ Object
The name of the action (e.g. `UsersController#show`) that is being executed.
-
#count ⇒ Object
Returns the value of attribute count.
Class Method Summary collapse
- .current ⇒ Object
-
.run ⇒ Object
Starts a new transaction and returns it and the blocks' return value.
Instance Method Summary collapse
-
#act_upon_results ⇒ Object
Sends a notification based on the number of executed SQL queries.
- #enabled? ⇒ Boolean
- #error_message ⇒ Object
- #executed_sql(sql) ⇒ Object
-
#ignorable?(sql) ⇒ Boolean
queries can be safely ignored if they are amoritized in regular usage (i.e. only requested occasionally and otherwise cached).
- #increment(sql = nil) ⇒ Object
-
#initialize ⇒ Transaction
constructor
A new instance of Transaction.
- #raise_error? ⇒ Boolean
- #threshold_exceeded? ⇒ Boolean
Constructor Details
#initialize ⇒ Transaction
Returns a new instance of Transaction.
45 46 47 48 49 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 45 def initialize @action = nil @count = 0 @sql_executed = [] end |
Instance Attribute Details
#action ⇒ Object
The name of the action (e.g. `UsersController#show`) that is being executed.
12 13 14 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 12 def action @action end |
#count ⇒ Object
Returns the value of attribute count.
8 9 10 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 8 def count @count end |
Class Method Details
.current ⇒ Object
23 24 25 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 23 def self.current Thread.current[THREAD_KEY] end |
.run ⇒ Object
Starts a new transaction and returns it and the blocks' return value.
Example:
transaction, retval = Transaction.run do
10
end
retval # => 10
36 37 38 39 40 41 42 43 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 36 def self.run transaction = new Thread.current[THREAD_KEY] = transaction [transaction, yield] ensure Thread.current[THREAD_KEY] = nil end |
Instance Method Details
#act_upon_results ⇒ Object
Sends a notification based on the number of executed SQL queries.
52 53 54 55 56 57 58 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 52 def act_upon_results return unless threshold_exceeded? error = ThresholdExceededError.new() raise(error) if raise_error? end |
#enabled? ⇒ Boolean
100 101 102 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 100 def enabled? ::Gitlab::QueryLimiting.enabled? end |
#error_message ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 90 def header = 'Too many SQL queries were executed' header = "#{header} in #{action}" if action msg = "a maximum of #{THRESHOLD} is allowed but #{count} SQL queries were executed" log = @sql_executed.each_with_index.map { |sql, i| "#{i}: #{sql}" }.join("\n").presence ellipsis = '...' if @count > LOG_THRESHOLD ["#{header}: #{msg}", log, ellipsis].compact.join("\n") end |
#executed_sql(sql) ⇒ Object
76 77 78 79 80 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 76 def executed_sql(sql) return if @count > LOG_THRESHOLD || ignorable?(sql) @sql_executed << sql end |
#ignorable?(sql) ⇒ Boolean
queries can be safely ignored if they are amoritized in regular usage (i.e. only requested occasionally and otherwise cached).
69 70 71 72 73 74 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 69 def ignorable?(sql) return true if sql&.include?(GEO_NODES_LOAD) return true if sql&.include?(LICENSES_LOAD) false end |
#increment(sql = nil) ⇒ Object
60 61 62 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 60 def increment(sql = nil) @count += 1 if enabled? && !ignorable?(sql) end |
#raise_error? ⇒ Boolean
82 83 84 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 82 def raise_error? Rails.env.test? end |
#threshold_exceeded? ⇒ Boolean
86 87 88 |
# File 'lib/gitlab/query_limiting/transaction.rb', line 86 def threshold_exceeded? count > THRESHOLD end |