Add a background migration to rename `uploads` in the uploads table
This commit is contained in:
		
							parent
							
								
									79f591df4d
								
							
						
					
					
						commit
						c156030ef9
					
				| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
class EnqueueMigrateSystemUploadsToNewFolder < ActiveRecord::Migration
 | 
			
		||||
  include Gitlab::Database::MigrationHelpers
 | 
			
		||||
 | 
			
		||||
  DOWNTIME = false
 | 
			
		||||
 | 
			
		||||
  OLD_FOLDER = 'uploads/system/'
 | 
			
		||||
  NEW_FOLDER = 'uploads/-/system/'
 | 
			
		||||
 | 
			
		||||
  disable_ddl_transaction!
 | 
			
		||||
 | 
			
		||||
  def up
 | 
			
		||||
    BackgroundMigrationWorker.perform_async('MigrateSystemUploadsToNewFolder',
 | 
			
		||||
                                            [OLD_FOLDER, NEW_FOLDER])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def down
 | 
			
		||||
    BackgroundMigrationWorker.perform_async('MigrateSystemUploadsToNewFolder',
 | 
			
		||||
                                            [NEW_FOLDER, OLD_FOLDER])
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,7 @@
 | 
			
		|||
#
 | 
			
		||||
# It's strongly recommended that you check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema.define(version: 20170717111152) do
 | 
			
		||||
ActiveRecord::Schema.define(version: 20170717150329) do
 | 
			
		||||
 | 
			
		||||
  # These are extensions that must be enabled in order to support this database
 | 
			
		||||
  enable_extension "plpgsql"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
module Gitlab
 | 
			
		||||
  module BackgroundMigration
 | 
			
		||||
    class MigrateSystemUploadsToNewFolder
 | 
			
		||||
      include Gitlab::Database::MigrationHelpers
 | 
			
		||||
      attr_reader :old_folder, :new_folder
 | 
			
		||||
 | 
			
		||||
      def perform(old_folder, new_folder)
 | 
			
		||||
        @old_folder = old_folder
 | 
			
		||||
        @new_folder = new_folder
 | 
			
		||||
 | 
			
		||||
        replace_sql = replace_sql(uploads[:path], old_folder, new_folder)
 | 
			
		||||
 | 
			
		||||
        while remaining_rows > 0
 | 
			
		||||
          sql = "UPDATE uploads "\
 | 
			
		||||
                "SET path = #{replace_sql} "\
 | 
			
		||||
                "WHERE uploads.id IN "\
 | 
			
		||||
                "  (SELECT uploads.id FROM uploads "\
 | 
			
		||||
                "  WHERE #{affected_uploads.to_sql} LIMIT 1000)"
 | 
			
		||||
          connection.execute(sql)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def uploads
 | 
			
		||||
        Arel::Table.new('uploads')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def remaining_rows
 | 
			
		||||
        remaining_result = connection.exec_query("SELECT count(id) FROM uploads WHERE #{affected_uploads.to_sql}")
 | 
			
		||||
        remaining = remaining_result.first['count'].to_i
 | 
			
		||||
        logger.info "#{remaining} uploads remaining"
 | 
			
		||||
        remaining
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def affected_uploads
 | 
			
		||||
        uploads[:path].matches("#{old_folder}%")
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def connection
 | 
			
		||||
        ActiveRecord::Base.connection
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def logger
 | 
			
		||||
        Sidekiq.logger || Rails.logger || Logger.new(STDOUT)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe Gitlab::BackgroundMigration::MigrateSystemUploadsToNewFolder do
 | 
			
		||||
  let(:migration) { described_class.new }
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    allow(migration).to receive(:logger).and_return(Logger.new(nil))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    it 'renames the path of system-uploads', truncate: true do
 | 
			
		||||
      upload = create(:upload, model: create(:empty_project), path: 'uploads/system/project/avatar.jpg')
 | 
			
		||||
 | 
			
		||||
      migration.perform('uploads/system/', 'uploads/-/system/')
 | 
			
		||||
 | 
			
		||||
      expect(upload.reload.path).to eq('uploads/-/system/project/avatar.jpg')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
		Reference in New Issue