prepare_unhashed_uploads.rb 2.35 KB
Newer Older
1
2
3
module Gitlab
  module BackgroundMigration
    class PrepareUnhashedUploads
4
5
6
      # For bulk_queue_background_migration_jobs_by_range
      include Database::MigrationHelpers

7
      FILE_PATH_BATCH_SIZE = 500
Michael Kozono's avatar
Michael Kozono committed
8
9
      UPLOAD_DIR = "#{CarrierWave.root}/uploads".freeze
      FOLLOW_UP_MIGRATION = 'PopulateUntrackedUploads'.freeze
10

11
      class UnhashedUploadFile < ActiveRecord::Base
12
13
        include EachBatch

14
15
16
17
18
19
        self.table_name = 'unhashed_upload_files'
      end

      def perform
        return unless migrate?

20
21
        clear_unhashed_upload_file_paths
        store_unhashed_upload_file_paths
22
23
24
25
26
27
28
29
30
        schedule_populate_untracked_uploads_jobs
      end

      private

      def migrate?
        UnhashedUploadFile.table_exists?
      end

31
32
      def clear_unhashed_upload_file_paths
        UnhashedUploadFile.delete_all
33
34
      end

35
      def store_unhashed_upload_file_paths
Michael Kozono's avatar
Michael Kozono committed
36
        return unless Dir.exist?(UPLOAD_DIR)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

        file_paths = []
        each_file_path(UPLOAD_DIR) do |file_path|
          file_paths << file_path

          if file_paths.size >= FILE_PATH_BATCH_SIZE
            insert_file_paths(file_paths)
            file_paths = []
          end
        end

        insert_file_paths(file_paths) if file_paths.any?
      end

      def each_file_path(search_dir, &block)
        cmd = build_find_command(search_dir)
        Open3.popen2(*cmd) do |stdin, stdout, status_thread|
          stdout.each_line("\0") do |line|
            yield(line.chomp("\0"))
          end
          raise "Find command failed" unless status_thread.value.success?
        end
      end

      def build_find_command(search_dir)
        cmd = ['find', search_dir, '-type', 'f', '!', '-path', "#{UPLOAD_DIR}/@hashed/*", '!', '-path', "#{UPLOAD_DIR}/tmp/*", '-print0']

        ['ionice', '-c', 'Idle'] + cmd if ionice_is_available?

        cmd
      end

      def ionice_is_available?
        Gitlab::Utils.which('ionice')
      rescue StandardError
        # In this case, returning false is relatively safe, even though it isn't very nice
        false
      end

      def insert_file_paths(file_paths)
        file_paths.each do |file_path|
          UnhashedUploadFile.create!(path: file_path)
        end
80
81
82
      end

      def schedule_populate_untracked_uploads_jobs
83
        bulk_queue_background_migration_jobs_by_range(UnhashedUploadFile, FOLLOW_UP_MIGRATION)
84
85
86
87
      end
    end
  end
end