Skip to content
代码片段 群组 项目
未验证 提交 78558a8c 编辑于 作者: Marius Bobin's avatar Marius Bobin
浏览文件

Keep locking_version when updating partitioned records

Optimistic locking is overriding the query_constraints method
and our patch was overriding it instead of overriding the
original method and the locking_version attribute was
lost during the update

Changelog: fixed
上级 30176ecc
No related branches found
No related tags found
无相关合并请求
...@@ -34,9 +34,12 @@ module Partitioning ...@@ -34,9 +34,12 @@ module Partitioning
::ActiveRecord::Reflection::MacroReflection.prepend( ::ActiveRecord::Reflection::MacroReflection.prepend(
ActiveRecord::GitlabPatches::Partitioning::Reflection::MacroReflection ActiveRecord::GitlabPatches::Partitioning::Reflection::MacroReflection
) )
::ActiveRecord::Base.prepend( ::ActiveRecord::Persistence.prepend(
ActiveRecord::GitlabPatches::Partitioning::Base ActiveRecord::GitlabPatches::Partitioning::Base
) )
::ActiveRecord::Persistence::ClassMethods.prepend(
ActiveRecord::GitlabPatches::Partitioning::Base::ClassMethods
)
end end
end end
end end
......
...@@ -4,19 +4,18 @@ ...@@ -4,19 +4,18 @@
raise 'New version of active-record detected, please remove or update this patch' raise 'New version of active-record detected, please remove or update this patch'
end end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
module ActiveRecord module ActiveRecord
module GitlabPatches module GitlabPatches
module Partitioning module Partitioning
module Base module Base
extend ActiveSupport::Concern
def _query_constraints_hash def _query_constraints_hash
constraints_hash = super constraints_hash = super
return constraints_hash unless self.class.use_partition_id_filter? return constraints_hash unless self.class.use_partition_id_filter?
if self.class.query_constraints_list.nil? if self.class.query_constraints_list.nil?
{ @primary_key => id_in_database } # rubocop:disable Gitlab/ModuleWithInstanceVariables { @primary_key => id_in_database }
else else
self.class.query_constraints_list.index_with do |column_name| self.class.query_constraints_list.index_with do |column_name|
attribute_in_database(column_name) attribute_in_database(column_name)
...@@ -24,7 +23,7 @@ def _query_constraints_hash ...@@ -24,7 +23,7 @@ def _query_constraints_hash
end end
end end
class_methods do module ClassMethods
def use_partition_id_filter? def use_partition_id_filter?
false false
end end
...@@ -47,3 +46,4 @@ def query_constraints_list # :nodoc: ...@@ -47,3 +46,4 @@ def query_constraints_list # :nodoc:
end end
end end
end end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
# frozen_string_literal: true
RSpec.describe 'ActiveRecord::GitlabPatches::Partitioning::Associations::Locking', :partitioning do
let!(:job) { LockingJob.create!(partition_id: 100) }
describe 'optimistic locking' do
it 'does not use lock version on unrelated updates' do
update_statement = <<~SQL.squish
UPDATE "locking_jobs" SET "name" = 'test'
WHERE "locking_jobs"."id" = #{job.id} AND "locking_jobs"."partition_id" = #{job.partition_id}
SQL
result = QueryRecorder.log do
job.update!(name: 'test')
end
expect(result).to include(update_statement)
end
it 'uses lock version when status changes' do
update_statement = <<~SQL.squish
UPDATE "locking_jobs"
SET "status" = 1, "name" = 'test', "lock_version" = 1
WHERE "locking_jobs"."id" = 1 AND "locking_jobs"."partition_id" = 100 AND "locking_jobs"."lock_version" = 0
SQL
result = QueryRecorder.log do
job.update!(name: 'test', status: :completed)
end
expect(result).to include(update_statement)
end
end
end
...@@ -24,6 +24,14 @@ ...@@ -24,6 +24,14 @@
t.integer :partition_id t.integer :partition_id
t.boolean :test_flag, default: false t.boolean :test_flag, default: false
end end
create_table :locking_jobs, force: true do |t|
t.integer :pipeline_id
t.integer :partition_id
t.integer :lock_version, default: 0, null: false
t.integer :status, default: 0, null: false
t.string :name
end
end end
end end
end end
...@@ -48,3 +48,14 @@ class Metadata < PartitionedRecord ...@@ -48,3 +48,14 @@ class Metadata < PartitionedRecord
belongs_to :job, belongs_to :job,
->(metadata) { where(partition_id: metadata.partition_id) } ->(metadata) { where(partition_id: metadata.partition_id) }
end end
class LockingJob < PartitionedRecord
self.table_name = :locking_jobs
query_constraints :id, :partition_id
enum status: { created: 0, completed: 1 }
def locking_enabled?
will_save_change_to_status?
end
end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册