debian-mirror-gitlab/app/services/repositories/housekeeping_service.rb
2023-03-17 16:20:25 +05:30

98 lines
2.2 KiB
Ruby

# frozen_string_literal: true
# Used for git housekeeping
#
# Ex.
# Repositories::HousekeepingService.new(project).execute
# Repositories::HousekeepingService.new(project.wiki).execute
#
module Repositories
class HousekeepingService < BaseService
# Timeout set to 24h
LEASE_TIMEOUT = 86400
GC_PERIOD = 200
class LeaseTaken < StandardError
def to_s
"Somebody already triggered housekeeping for this resource in the past #{LEASE_TIMEOUT / 60} minutes"
end
end
def initialize(resource, task = nil)
@resource = resource
@task = task
end
def execute
lease_uuid = try_obtain_lease
raise LeaseTaken unless lease_uuid.present?
yield if block_given?
execute_gitlab_shell_gc(lease_uuid)
end
def needed?
pushes_since_gc > 0 && period_match? && housekeeping_enabled?
end
def increment!
Gitlab::Metrics.measure(:increment_pushes_since_gc) do
@resource.increment_pushes_since_gc
end
end
private
def execute_gitlab_shell_gc(lease_uuid)
@resource.git_garbage_collect_worker_klass.perform_async(@resource.id, task, lease_key, lease_uuid)
ensure
if pushes_since_gc >= gc_period
Gitlab::Metrics.measure(:reset_pushes_since_gc) do
@resource.reset_pushes_since_gc
end
end
end
def try_obtain_lease
Gitlab::Metrics.measure(:obtain_housekeeping_lease) do
lease = ::Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT)
lease.try_obtain
end
end
def lease_key
"#{@resource.class.name.underscore.pluralize}_housekeeping:#{@resource.id}"
end
def pushes_since_gc
@resource.pushes_since_gc
end
def task
return @task if @task
if pushes_since_gc % gc_period == 0
:gc
else
:incremental_repack
end
end
def period_match?
[gc_period, repack_period].any? { |period| pushes_since_gc % period == 0 }
end
def housekeeping_enabled?
Gitlab::CurrentSettings.housekeeping_enabled
end
def gc_period
GC_PERIOD
end
def repack_period
Gitlab::CurrentSettings.housekeeping_incremental_repack_period
end
end
end