Class: CreatedId::IdRange
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- CreatedId::IdRange
- Defined in:
- lib/created_id/id_range.rb
Overview
This model stores the id ranges for other models by the hour. It is not meant to be accessed directly.
Class Method Summary collapse
-
.id_range(klass, time) ⇒ Array<Integer>
Get the minimum and maximum ids for a model created in a given hour.
-
.max_id(klass, time, allow_nil: false) ⇒ Integer?
Get the maximum id for a class created in a given hour.
-
.min_id(klass, time, allow_nil: false) ⇒ Integer?
Get the minimum id for a class created in a given hour.
-
.save_created_id(klass, time, min_id, max_id) ⇒ void
Save the minimum and maximum ids for a class created in a given hour.
Class Method Details
.id_range(klass, time) ⇒ Array<Integer>
Get the minimum and maximum ids for a model created in a given hour. This method is used in indexing the ranges.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/created_id/id_range.rb', line 67 def id_range(klass, time) klass = klass.base_class hour = CreatedId.coerce_hour(time) next_hour = hour + 3600 finder = klass.unscoped.where(created_at: (hour...next_hour)) # Lower bound: the min id of the latest indexed hour strictly before this one. # A record in this hour can never have an id at or below the previous indexed # hour's minimum, even when ids are out of order near the boundary. prev_id = for_class(klass).where(hour: nil...hour).order(hour: :desc).first&.min_id finder = finder.where(klass.arel_table[:id].gt(prev_id)) if prev_id && prev_id > 0 # Upper bound: the min id of the earliest indexed hour at least two hours after # this one. The immediately following hour is skipped because its id range may # legitimately overlap this hour's when ids are out of order near the boundary. next_id = for_class(klass).created_after(next_hour + 3600).order(hour: :asc).first&.min_id if next_id && (prev_id.nil? || next_id > prev_id) finder = finder.where(klass.arel_table[:id].lt(next_id)) end [finder.minimum(:id), finder.maximum(:id)] end |
.max_id(klass, time, allow_nil: false) ⇒ Integer?
Get the maximum id for a class created in a given hour.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/created_id/id_range.rb', line 44 def max_id(klass, time, allow_nil: false) return nil if time.nil? && allow_nil id = for_class(klass).created_after(CreatedId.coerce_hour(time)).order(hour: :asc).first&.max_id if id.nil? && !allow_nil col_limit = klass.columns.detect { |c| c.name == klass.primary_key }.limit id = if col_limit && col_limit > 0 ((256**col_limit) / 2) - 1 else klass.base_class.unscoped.maximum(:id).to_i end end id end |
.min_id(klass, time, allow_nil: false) ⇒ Integer?
Get the minimum id for a class created in a given hour.
29 30 31 32 33 34 35 |
# File 'lib/created_id/id_range.rb', line 29 def min_id(klass, time, allow_nil: false) return nil if time.nil? && allow_nil id = for_class(klass).created_before(time).order(hour: :desc).first&.min_id id ||= 0 unless allow_nil id end |
.save_created_id(klass, time, min_id, max_id) ⇒ void
This method returns an undefined value.
Save the minimum and maximum ids for a class created in a given hour.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/created_id/id_range.rb', line 98 def save_created_id(klass, time, min_id, max_id) retried = false begin record = find_or_initialize_by(class_name: klass.base_class.name, hour: CreatedId.coerce_hour(time)) record.min_id = min_id record.max_id = max_id record.save! rescue ActiveRecord::RecordNotUnique # A concurrent process indexed the same hour first; retry to update its record. raise if retried retried = true retry end end |