Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									6cd5b7dbfa
								
							
						
					
					
						commit
						26804e91d9
					
				|  | @ -0,0 +1,5 @@ | ||||||
|  | --- | ||||||
|  | title: Sync issuables state_id with null values | ||||||
|  | merge_request: 16480 | ||||||
|  | author: | ||||||
|  | type: other | ||||||
|  | @ -0,0 +1,79 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | # Sync remaining records for issues/merge_requests tables where state_id | ||||||
|  | # is still null. | ||||||
|  | # For more information check: https://gitlab.com/gitlab-org/gitlab-ee/issues/26823 | ||||||
|  | # It creates a temporary index before performing the UPDATES to sync values. | ||||||
|  | # | ||||||
|  | # In 09-11-2019 we have the following numbers for records with state_id == nil: | ||||||
|  | # | ||||||
|  | # 1348 issues - default batch size for each update 67 | ||||||
|  | # 10247 merge requests - default batch size for each update 511 | ||||||
|  | 
 | ||||||
|  | class SyncIssuablesStateId < ActiveRecord::Migration[5.2] | ||||||
|  |   include Gitlab::Database::MigrationHelpers | ||||||
|  | 
 | ||||||
|  |   DOWNTIME = false | ||||||
|  | 
 | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     %i(issues merge_requests).each do |table| | ||||||
|  |       temp_index_name = index_name_for(table) | ||||||
|  | 
 | ||||||
|  |       add_concurrent_index( | ||||||
|  |         table, | ||||||
|  |         'id', | ||||||
|  |         name: temp_index_name, | ||||||
|  |         where: 'state_id IS NULL' | ||||||
|  |       ) | ||||||
|  | 
 | ||||||
|  |       update_value = update_condition_for(table) | ||||||
|  | 
 | ||||||
|  |       update_column_in_batches(table, :state_id, update_value) do |table, query| | ||||||
|  |         query.where(table[:state_id].eq(nil)) | ||||||
|  |       end | ||||||
|  |     ensure | ||||||
|  |       remove_concurrent_index_by_name(table, temp_index_name) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     # NO OP | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def update_condition_for(table) | ||||||
|  |     value_expresson = | ||||||
|  |       if table == :issues | ||||||
|  |         issues_state_id_condition | ||||||
|  |       else | ||||||
|  |         merge_requests_state_id_condition | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |     Arel.sql(value_expresson) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def index_name_for(table) | ||||||
|  |     "idx_tmp_on_#{table}_where_state_id_is_null" | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def issues_state_id_condition | ||||||
|  |     <<~SQL | ||||||
|  |       CASE state | ||||||
|  |       WHEN 'opened' THEN 1 | ||||||
|  |       WHEN 'closed' THEN 2 | ||||||
|  |       END | ||||||
|  |     SQL | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def merge_requests_state_id_condition | ||||||
|  |     <<~SQL | ||||||
|  |       CASE state | ||||||
|  |       WHEN 'opened' THEN 1 | ||||||
|  |       WHEN 'closed' THEN 2 | ||||||
|  |       WHEN 'merged' THEN 3 | ||||||
|  |       WHEN 'locked' THEN 4 | ||||||
|  |       END | ||||||
|  |     SQL | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | require 'spec_helper' | ||||||
|  | require Rails.root.join('db', 'post_migrate', '20190911251732_sync_issuables_state_id') | ||||||
|  | 
 | ||||||
|  | describe SyncIssuablesStateId, :migration, :sidekiq do | ||||||
|  |   let(:migration) { described_class.new } | ||||||
|  | 
 | ||||||
|  |   describe '#up' do | ||||||
|  |     let(:issues) { table(:issues) } | ||||||
|  |     let(:namespaces) { table(:namespaces) } | ||||||
|  |     let(:projects) { table(:projects) } | ||||||
|  |     let(:merge_requests) { table(:merge_requests) } | ||||||
|  |     let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') } | ||||||
|  |     let(:project) { projects.create!(namespace_id: group.id) } | ||||||
|  |     # These state_ids should be the same defined on Issue/MergeRequest models | ||||||
|  |     let(:state_ids) { { opened: 1, closed: 2, merged: 3, locked: 4 } } | ||||||
|  | 
 | ||||||
|  |     it 'migrates state column to state_id as integer' do | ||||||
|  |       opened_issue = issues.create!(description: 'first', state: 'opened') | ||||||
|  |       closed_issue = issues.create!(description: 'second', state: 'closed') | ||||||
|  |       opened_merge_request = merge_requests.create!(state: 'opened', target_project_id: project.id, target_branch: 'feature1', source_branch: 'master') | ||||||
|  |       closed_merge_request = merge_requests.create!(state: 'closed', target_project_id: project.id, target_branch: 'feature2', source_branch: 'master') | ||||||
|  |       merged_merge_request = merge_requests.create!(state: 'merged', target_project_id: project.id, target_branch: 'feature3', source_branch: 'master') | ||||||
|  |       locked_merge_request = merge_requests.create!(state: 'locked', target_project_id: project.id, target_branch: 'feature4', source_branch: 'master') | ||||||
|  | 
 | ||||||
|  |       migrate! | ||||||
|  | 
 | ||||||
|  |       expect(opened_issue.reload.state_id).to eq(state_ids[:opened]) | ||||||
|  |       expect(closed_issue.reload.state_id).to eq(state_ids[:closed]) | ||||||
|  |       expect(opened_merge_request.reload.state_id).to eq(state_ids[:opened]) | ||||||
|  |       expect(closed_merge_request.reload.state_id).to eq(state_ids[:closed]) | ||||||
|  |       expect(merged_merge_request.reload.state_id).to eq(state_ids[:merged]) | ||||||
|  |       expect(locked_merge_request.reload.state_id).to eq(state_ids[:locked]) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
		Loading…
	
		Reference in New Issue