Module: AtomicInternalId
- Extended by:
- ActiveSupport::Concern
- Included in:
- AlertManagement::Alert, Ci::Pipeline, Deployment, DesignManagement::Design, Issue, MergeRequest, Milestone, Ml::Candidate, Ml::Experiment, Operations::FeatureFlag, Operations::FeatureFlags::UserList
- Defined in:
- app/models/concerns/atomic_internal_id.rb
Overview
Include atomic internal id generation scheme for a model
This allows us to atomically generate internal ids that are unique within a given scope.
For example, let’s generate internal ids for Issue per Project: “‘ class Issue < ApplicationRecord
has_internal_id :iid, scope: :project, init: ->(s) { s.project.issues.maximum(:iid) }
end “‘
This generates unique internal ids per project for newly created issues. The generated internal id is saved in the ‘iid` attribute of `Issue`.
This concern uses InternalId records to facilitate atomicity. In the absence of a record for the given scope, one will be created automatically. In this situation, the ‘init` block is called to calculate the initial value. In the example above, we calculate the maximum `iid` of all issues within the given project.
Note that a model may have more than one internal id associated with possibly different scopes.
Defined Under Namespace
Classes: Supply
Constant Summary collapse
- MissingValueError =
Class.new(StandardError)
Class Method Summary collapse
- .group_init(klass, column_name = :iid) ⇒ Object
- .namespace_init(klass, column_name = :iid) ⇒ Object
- .project_init(klass, column_name = :iid) ⇒ Object
- .scope_attrs(scope_value) ⇒ Object
- .scope_usage(including_class) ⇒ Object
Instance Method Summary collapse
- #internal_id_read_scope(scope) ⇒ Object
- #internal_id_scope_attrs(scope) ⇒ Object
- #internal_id_scope_usage ⇒ Object
Class Method Details
.group_init(klass, column_name = :iid) ⇒ Object
236 237 238 239 240 241 242 243 244 |
# File 'app/models/concerns/atomic_internal_id.rb', line 236 def self.group_init(klass, column_name = :iid) ->(instance, scope) do if instance klass.where(group_id: instance.group_id).maximum(column_name) elsif scope.present? klass.where(group: scope[:namespace]).maximum(column_name) end end end |
.namespace_init(klass, column_name = :iid) ⇒ Object
246 247 248 249 250 251 252 253 254 |
# File 'app/models/concerns/atomic_internal_id.rb', line 246 def self.namespace_init(klass, column_name = :iid) ->(instance, scope) do if instance klass.where(namespace_id: instance.namespace_id).maximum(column_name) elsif scope.present? klass.where(**scope).maximum(column_name) end end end |
.project_init(klass, column_name = :iid) ⇒ Object
226 227 228 229 230 231 232 233 234 |
# File 'app/models/concerns/atomic_internal_id.rb', line 226 def self.project_init(klass, column_name = :iid) ->(instance, scope) do if instance klass.default_scoped.where(project_id: instance.project_id).maximum(column_name) elsif scope.present? klass.default_scoped.where(**scope).maximum(column_name) end end end |
.scope_attrs(scope_value) ⇒ Object
208 209 210 |
# File 'app/models/concerns/atomic_internal_id.rb', line 208 def self.scope_attrs(scope_value) { scope_value.class.table_name.singularize.to_sym => scope_value } if scope_value end |
.scope_usage(including_class) ⇒ Object
222 223 224 |
# File 'app/models/concerns/atomic_internal_id.rb', line 222 def self.scope_usage(including_class) including_class.table_name.to_sym end |
Instance Method Details
#internal_id_read_scope(scope) ⇒ Object
256 257 258 |
# File 'app/models/concerns/atomic_internal_id.rb', line 256 def internal_id_read_scope(scope) association(scope).reader end |
#internal_id_scope_attrs(scope) ⇒ Object
212 213 214 215 216 |
# File 'app/models/concerns/atomic_internal_id.rb', line 212 def internal_id_scope_attrs(scope) scope_value = internal_id_read_scope(scope) ::AtomicInternalId.scope_attrs(scope_value) end |
#internal_id_scope_usage ⇒ Object
218 219 220 |
# File 'app/models/concerns/atomic_internal_id.rb', line 218 def internal_id_scope_usage ::AtomicInternalId.scope_usage(self.class) end |