From 14acbf245582a1821896b94b567c5ca8ba064d4a Mon Sep 17 00:00:00 2001 From: Andreas Brandl Date: Mon, 16 Apr 2018 11:19:56 +0200 Subject: Double-check next value for internal ids. This is useful for a transition period to migrate away from `NoninternalAtomicId`. In a situation where both the old and new code to generate a iid value is run at the same time (for example, during a deploy different nodes may serve both versions), this will lead to problems regarding the correct `last_value`. That is, what we track in `InternalId` may get out of sync with the maximum iid present for issues. With this change, we double-check that and correct the `last_value` with the maximum iid found in issues if necessary. This is subject to be removed with the 10.8 release and tracked over here: https://gitlab.com/gitlab-org/gitlab-ce/issues/45389 Closes #45269. --- app/models/internal_id.rb | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'app/models/internal_id.rb') diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb index cbec735c2dd..96a43006642 100644 --- a/app/models/internal_id.rb +++ b/app/models/internal_id.rb @@ -23,9 +23,12 @@ class InternalId < ActiveRecord::Base # # The operation locks the record and gathers a `ROW SHARE` lock (in PostgreSQL). # As such, the increment is atomic and safe to be called concurrently. - def increment_and_save! + # + # If a `maximum_iid` is passed in, this overrides the incremented value if it's + # greater than that. This can be used to correct the increment value if necessary. + def increment_and_save!(maximum_iid) lock! - self.last_value = (last_value || 0) + 1 + self.last_value = [(last_value || 0) + 1, (maximum_iid || 0) + 1].max save! last_value end @@ -89,7 +92,16 @@ class InternalId < ActiveRecord::Base # and increment its last value # # Note this will acquire a ROW SHARE lock on the InternalId record - (lookup || create_record).increment_and_save! + + # Note we always calculate the maximum iid present here and + # pass it in to correct the InternalId entry if it's last_value is off. + # + # This can happen in a transition phase where both `AtomicInternalId` and + # `NonatomicInternalId` code runs (e.g. during a deploy). + # + # This is subject to be cleaned up with the 10.8 release: + # https://gitlab.com/gitlab-org/gitlab-ce/issues/45389. + (lookup || create_record).increment_and_save!(maximum_iid) end end @@ -115,11 +127,15 @@ class InternalId < ActiveRecord::Base InternalId.create!( **scope, usage: usage_value, - last_value: init.call(subject) || 0 + last_value: maximum_iid ) end rescue ActiveRecord::RecordNotUnique lookup end + + def maximum_iid + @maximum_iid ||= init.call(subject) || 0 + end end end -- cgit v1.2.3