Class: Gitlab::Database::BatchAverageCounter
- Inherits:
-
Object
- Object
- Gitlab::Database::BatchAverageCounter
- Defined in:
- lib/gitlab/database/batch_average_counter.rb
Constant Summary collapse
- COLUMN_FALLBACK =
0
- DEFAULT_BATCH_SIZE =
1_000
- FALLBACK =
-1
- MAX_ALLOWED_LOOPS =
10_000
- OFFSET_BY_ONE =
1
- SLEEP_TIME_IN_SECONDS =
10 msec sleep
0.01
Instance Attribute Summary collapse
-
#column ⇒ Object
readonly
Returns the value of attribute column.
-
#relation ⇒ Object
readonly
Returns the value of attribute relation.
Instance Method Summary collapse
- #count(batch_size: nil) ⇒ Object
-
#initialize(relation, column) ⇒ BatchAverageCounter
constructor
A new instance of BatchAverageCounter.
Constructor Details
#initialize(relation, column) ⇒ BatchAverageCounter
Returns a new instance of BatchAverageCounter.
15 16 17 18 |
# File 'lib/gitlab/database/batch_average_counter.rb', line 15 def initialize(relation, column) @relation = relation @column = wrap_column(relation, column) end |
Instance Attribute Details
#column ⇒ Object (readonly)
Returns the value of attribute column.
13 14 15 |
# File 'lib/gitlab/database/batch_average_counter.rb', line 13 def column @column end |
#relation ⇒ Object (readonly)
Returns the value of attribute relation.
13 14 15 |
# File 'lib/gitlab/database/batch_average_counter.rb', line 13 def relation @relation end |
Instance Method Details
#count(batch_size: nil) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/gitlab/database/batch_average_counter.rb', line 20 def count(batch_size: nil) raise 'BatchAverageCounter can not be run inside a transaction' if transaction_open? batch_size = batch_size.presence || DEFAULT_BATCH_SIZE start = column_start finish = column_finish total_sum = 0 total_records = 0 batch_start = start while batch_start < finish begin batch_end = [batch_start + batch_size, finish].min batch_relation = build_relation_batch(batch_start, batch_end) # We use `sum` and `count` instead of `average` here to not run into an "average of averages" # problem as batches will have different sizes, so we are essentially summing up the values for # each batch separately, and then dividing that result on the total number of records. batch_sum, batch_count = batch_relation.pick(column.sum, column.count) total_sum += batch_sum.to_i total_records += batch_count batch_start = batch_end rescue ActiveRecord::QueryCanceled => error # rubocop:disable Database/RescueQueryCanceled # retry with a safe batch size & warmer cache if batch_size >= 2 * DEFAULT_BATCH_SIZE batch_size /= 2 else log_canceled_batch_fetch(batch_start, batch_relation.to_sql, error) return FALLBACK end end sleep(SLEEP_TIME_IN_SECONDS) end return FALLBACK if total_records == 0 total_sum.to_f / total_records end |