debian-mirror-gitlab/lib/gitlab/git/storage/circuit_breaker.rb

78 lines
2.2 KiB
Ruby
Raw Normal View History

2017-09-10 17:25:29 +05:30
module Gitlab
module Git
module Storage
class CircuitBreaker
2018-03-17 18:26:18 +05:30
include CircuitBreakerSettings
2017-09-10 17:25:29 +05:30
attr_reader :storage,
2018-03-17 18:26:18 +05:30
:hostname
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
delegate :last_failure, :failure_count, :no_failures?,
to: :failure_info
2017-09-10 17:25:29 +05:30
def self.for_storage(storage)
cached_circuitbreakers = RequestStore.fetch(:circuitbreaker_cache) do
Hash.new do |hash, storage_name|
2018-03-17 18:26:18 +05:30
hash[storage_name] = build(storage_name)
2017-09-10 17:25:29 +05:30
end
end
cached_circuitbreakers[storage]
end
2018-03-17 18:26:18 +05:30
def self.build(storage, hostname = Gitlab::Environment.hostname)
config = Gitlab.config.repositories.storages[storage]
if !config.present?
NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Storage '#{storage}' is not configured"))
2018-05-09 12:01:36 +05:30
elsif !config.legacy_disk_path.present?
2018-03-17 18:26:18 +05:30
NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Path for storage '#{storage}' is not configured"))
else
new(storage, hostname)
end
end
def initialize(storage, hostname)
2017-09-10 17:25:29 +05:30
@storage = storage
@hostname = hostname
end
def perform
2018-03-17 18:26:18 +05:30
return yield unless enabled?
2017-09-10 17:25:29 +05:30
check_storage_accessible!
yield
end
def circuit_broken?
return false if no_failures?
2018-03-17 18:26:18 +05:30
failure_count > failure_count_threshold
2017-09-10 17:25:29 +05:30
end
2018-03-17 18:26:18 +05:30
private
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
# The circuitbreaker can be enabled for the entire fleet using a Feature
# flag.
#
# Enabling it for a single host can be done setting the
# `GIT_STORAGE_CIRCUIT_BREAKER` environment variable.
def enabled?
ENV['GIT_STORAGE_CIRCUIT_BREAKER'].present? || Feature.enabled?('git_storage_circuit_breaker')
2017-09-10 17:25:29 +05:30
end
def failure_info
2018-03-17 18:26:18 +05:30
@failure_info ||= FailureInfo.load(cache_key)
2017-09-10 17:25:29 +05:30
end
2018-03-17 18:26:18 +05:30
def check_storage_accessible!
if circuit_broken?
raise Gitlab::Git::Storage::CircuitOpen.new("Circuit for #{storage} is broken", failure_reset_time)
2017-09-10 17:25:29 +05:30
end
end
end
end
end
end