summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/link_lfs_objects_projects.rb
blob: 983470c5121498e344c61d7541b5ed2d76d26953 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
80
81
82
# frozen_string_literal: true

module Gitlab
  module BackgroundMigration
    # Create missing LfsObjectsProject records for forks
    class LinkLfsObjectsProjects
      # Model specifically used for migration.
      class LfsObjectsProject < ActiveRecord::Base
        include EachBatch

        self.table_name = 'lfs_objects_projects'

        def self.linkable
          where(
            <<~SQL
              lfs_objects_projects.project_id IN (
                SELECT fork_network_members.forked_from_project_id
                FROM fork_network_members
                WHERE fork_network_members.forked_from_project_id IS NOT NULL
              )
            SQL
          )
        end
      end

      # Model specifically used for migration.
      class ForkNetworkMember < ActiveRecord::Base
        include EachBatch

        self.table_name = 'fork_network_members'

        def self.without_lfs_object(lfs_object_id)
          where(
            <<~SQL
              fork_network_members.project_id NOT IN (
                SELECT lop.project_id
                FROM lfs_objects_projects lop
                WHERE lop.lfs_object_id = #{lfs_object_id}
              )
            SQL
          )
        end
      end

      BATCH_SIZE = 1000

      def perform(start_id, end_id)
        lfs_objects_projects =
          Gitlab::BackgroundMigration::LinkLfsObjectsProjects::LfsObjectsProject
            .linkable
            .where(id: start_id..end_id)

        return if lfs_objects_projects.empty?

        lfs_objects_projects.find_each do |lop|
          ForkNetworkMember
            .select("#{lop.lfs_object_id}, fork_network_members.project_id, NOW(), NOW()")
            .without_lfs_object(lop.lfs_object_id)
            .where(forked_from_project_id: lop.project_id)
            .each_batch(of: BATCH_SIZE) do |batch, index|
              execute <<~SQL
                INSERT INTO lfs_objects_projects (lfs_object_id, project_id, created_at, updated_at)
                #{batch.to_sql}
              SQL

              logger.info(message: "LinkLfsObjectsProjects: created missing LfsObjectsProject records for LfsObject #{lop.lfs_object_id}")
            end
        end
      end

      private

      def execute(sql)
        ::ActiveRecord::Base.connection.execute(sql)
      end

      def logger
        @logger ||= Gitlab::BackgroundMigration::Logger.build
      end
    end
  end
end