housekeeping_service.rb 2.26 KB
Newer Older
1 2
# frozen_string_literal: true

3 4 5 6 7
# Projects::HousekeepingService class
#
# Used for git housekeeping
#
# Ex.
8
#   Projects::HousekeepingService.new(project).execute
9 10 11
#
module Projects
  class HousekeepingService < BaseService
12 13
    # Timeout set to 24h
    LEASE_TIMEOUT = 86400
14

15 16 17 18 19 20
    class LeaseTaken < StandardError
      def to_s
        "Somebody already triggered housekeeping for this project in the past #{LEASE_TIMEOUT / 60} minutes"
      end
    end

21 22 23 24 25
    def initialize(project)
      @project = project
    end

    def execute
Jacob Vosmaer's avatar
Jacob Vosmaer committed
26 27
      lease_uuid = try_obtain_lease
      raise LeaseTaken unless lease_uuid.present?
Jacob Vosmaer's avatar
Jacob Vosmaer committed
28

29 30
      yield if block_given?

Jacob Vosmaer's avatar
Jacob Vosmaer committed
31
      execute_gitlab_shell_gc(lease_uuid)
Jacob Vosmaer's avatar
Jacob Vosmaer committed
32 33 34
    end

    def needed?
Jacob Vosmaer's avatar
Jacob Vosmaer committed
35
      pushes_since_gc > 0 && period_match? && housekeeping_enabled?
Jacob Vosmaer's avatar
Jacob Vosmaer committed
36 37 38
    end

    def increment!
Yorick Peterse's avatar
Yorick Peterse committed
39 40
      Gitlab::Metrics.measure(:increment_pushes_since_gc) do
        @project.increment_pushes_since_gc
41
      end
42 43 44 45
    end

    private

Jacob Vosmaer's avatar
Jacob Vosmaer committed
46 47
    def execute_gitlab_shell_gc(lease_uuid)
      GitGarbageCollectWorker.perform_async(@project.id, task, lease_key, lease_uuid)
48
    ensure
Jacob Vosmaer's avatar
Jacob Vosmaer committed
49 50 51 52
      if pushes_since_gc >= gc_period
        Gitlab::Metrics.measure(:reset_pushes_since_gc) do
          @project.reset_pushes_since_gc
        end
53 54 55
      end
    end

56
    def try_obtain_lease
57
      Gitlab::Metrics.measure(:obtain_housekeeping_lease) do
Jacob Vosmaer's avatar
Jacob Vosmaer committed
58
        lease = ::Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT)
59 60
        lease.try_obtain
      end
61
    end
Jacob Vosmaer's avatar
Jacob Vosmaer committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

    def lease_key
      "project_housekeeping:#{@project.id}"
    end

    def pushes_since_gc
      @project.pushes_since_gc
    end

    def task
      if pushes_since_gc % gc_period == 0
        :gc
      elsif pushes_since_gc % full_repack_period == 0
        :full_repack
      else
        :incremental_repack
      end
    end

    def period_match?
      [gc_period, full_repack_period, repack_period].any? { |period| pushes_since_gc % period == 0 }
    end

    def housekeeping_enabled?
86
      Gitlab::CurrentSettings.housekeeping_enabled
Jacob Vosmaer's avatar
Jacob Vosmaer committed
87 88 89
    end

    def gc_period
90
      Gitlab::CurrentSettings.housekeeping_gc_period
Jacob Vosmaer's avatar
Jacob Vosmaer committed
91 92 93
    end

    def full_repack_period
94
      Gitlab::CurrentSettings.housekeeping_full_repack_period
Jacob Vosmaer's avatar
Jacob Vosmaer committed
95 96 97
    end

    def repack_period
98
      Gitlab::CurrentSettings.housekeeping_incremental_repack_period
Jacob Vosmaer's avatar
Jacob Vosmaer committed
99
    end
100 101
  end
end