repository_backfill_service.rb 2.1 KB
Newer Older
1 2
module Geo
  class RepositoryBackfillService
3
    attr_reader :project
4

5
    LEASE_TIMEOUT = 8.hours.freeze
6

7
    def initialize(project)
8 9 10 11
      @project = project
    end

    def execute
12
      try_obtain_lease do
13
        fetch_repositories do |started_at, finished_at|
14 15 16 17 18 19 20 21 22 23
          registry = Geo::ProjectRegistry.find_or_create_by(project_id: project.id)
          registry.last_repository_synced_at = started_at
          registry.last_repository_successful_sync_at = finished_at if finished_at
          registry.save
        end
      end
    end

    private

24
    def fetch_repositories
25 26 27 28
      started_at  = DateTime.now
      finished_at = nil

      begin
29 30 31
        project.create_repository unless project.repository_exists?
        project.repository.after_create if project.empty_repo?
        project.repository.fetch_geo_mirror(ssh_url_to_repo)
32 33 34 35 36 37

        # Second .wiki call returns a Gollum::Wiki, and it will always create the physical repository when not found
        if project.wiki_enabled? && project.wiki.wiki.exist?
          project.wiki.repository.fetch_geo_mirror(ssh_url_to_wiki)
        end

38 39 40 41
        project.repository.expire_all_method_caches
        project.repository.expire_branch_cache
        project.repository.expire_content_cache

42 43 44
        finished_at = DateTime.now
      rescue Gitlab::Shell::Error => e
        Rails.logger.error("Error backfilling repository #{project.path_with_namespace}: #{e}")
45
      end
46

47 48
      yield started_at, finished_at
    end
49

50
    def try_obtain_lease
51
      uuid = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT).try_obtain
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

      return unless uuid

      yield

      release_lease(uuid)
    end

    def release_lease(uuid)
      Gitlab::ExclusiveLease.cancel(lease_key, uuid)
    end

    def lease_key
      @key ||= "repository_backfill_service:#{project.id}"
    end

68 69 70 71
    def primary_ssh_path_prefix
      Gitlab::Geo.primary_ssh_path_prefix
    end

72
    def ssh_url_to_repo
73 74 75 76 77
      "#{primary_ssh_path_prefix}#{project.path_with_namespace}.git"
    end

    def ssh_url_to_wiki
      "#{primary_ssh_path_prefix}#{project.path_with_namespace}.wiki.git"
78 79 80
    end
  end
end