Commit 15d00fc3 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'gitaly-398-git-garbage-collect' into 'master'

Migrate GitGarbageCollectWorker to Gitaly

Closes gitaly#398

See merge request !12975
parents 6fe736f2 05f90b86
...@@ -5,6 +5,12 @@ class GitGarbageCollectWorker ...@@ -5,6 +5,12 @@ class GitGarbageCollectWorker
sidekiq_options retry: false sidekiq_options retry: false
GITALY_MIGRATED_TASKS = {
gc: :garbage_collect,
full_repack: :repack_full,
incremental_repack: :repack_incremental
}.freeze
def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil) def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil)
project = Project.find(project_id) project = Project.find(project_id)
task = task.to_sym task = task.to_sym
...@@ -15,8 +21,14 @@ class GitGarbageCollectWorker ...@@ -15,8 +21,14 @@ class GitGarbageCollectWorker
Gitlab::GitLogger.info(description) Gitlab::GitLogger.info(description)
output, status = Gitlab::Popen.popen(cmd, repo_path) gitaly_migrate(GITALY_MIGRATED_TASKS[task]) do |is_enabled|
Gitlab::GitLogger.error("#{description} failed:\n#{output}") unless status.zero? if is_enabled
gitaly_call(task, project.repository.raw_repository)
else
output, status = Gitlab::Popen.popen(cmd, repo_path)
Gitlab::GitLogger.error("#{description} failed:\n#{output}") unless status.zero?
end
end
# Refresh the branch cache in case garbage collection caused a ref lookup to fail # Refresh the branch cache in case garbage collection caused a ref lookup to fail
flush_ref_caches(project) if task == :gc flush_ref_caches(project) if task == :gc
...@@ -26,6 +38,19 @@ class GitGarbageCollectWorker ...@@ -26,6 +38,19 @@ class GitGarbageCollectWorker
private private
## `repository` has to be a Gitlab::Git::Repository
def gitaly_call(task, repository)
client = Gitlab::GitalyClient::RepositoryService.new(repository)
case task
when :gc
client.garbage_collect(bitmaps_enabled?)
when :full_repack
client.repack_full(bitmaps_enabled?)
when :incremental_repack
client.repack_incremental
end
end
def command(task) def command(task)
case task case task
when :gc when :gc
...@@ -55,4 +80,14 @@ class GitGarbageCollectWorker ...@@ -55,4 +80,14 @@ class GitGarbageCollectWorker
config_value = write_bitmaps ? 'true' : 'false' config_value = write_bitmaps ? 'true' : 'false'
%W[git -c repack.writeBitmaps=#{config_value}] %W[git -c repack.writeBitmaps=#{config_value}]
end end
def gitaly_migrate(method, &block)
Gitlab::GitalyClient.migrate(method, &block)
rescue GRPC::NotFound => e
Gitlab::GitLogger.error("#{method} failed:\nRepository not found")
raise Gitlab::Git::Repository::NoRepository.new(e)
rescue GRPC::BadStatus => e
Gitlab::GitLogger.error("#{method} failed:\n#{e}")
raise Gitlab::Git::CommandError.new(e)
end
end end
...@@ -4,12 +4,28 @@ module Gitlab ...@@ -4,12 +4,28 @@ module Gitlab
def initialize(repository) def initialize(repository)
@repository = repository @repository = repository
@gitaly_repo = repository.gitaly_repository @gitaly_repo = repository.gitaly_repository
@storage = repository.storage
end end
def exists? def exists?
request = Gitaly::RepositoryExistsRequest.new(repository: @gitaly_repo) request = Gitaly::RepositoryExistsRequest.new(repository: @gitaly_repo)
GitalyClient.call(@repository.storage, :repository_service, :exists, request).exists GitalyClient.call(@storage, :repository_service, :exists, request).exists
end
def garbage_collect(create_bitmap)
request = Gitaly::GarbageCollectRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap)
GitalyClient.call(@storage, :repository_service, :garbage_collect, request)
end
def repack_full(create_bitmap)
request = Gitaly::RepackFullRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap)
GitalyClient.call(@storage, :repository_service, :repack_full, request)
end
def repack_incremental
request = Gitaly::RepackIncrementalRequest.new(repository: @gitaly_repo)
GitalyClient.call(@storage, :repository_service, :repack_incremental, request)
end end
end end
end end
......
...@@ -9,17 +9,51 @@ describe GitGarbageCollectWorker do ...@@ -9,17 +9,51 @@ describe GitGarbageCollectWorker do
subject { described_class.new } subject { described_class.new }
describe "#perform" do describe "#perform" do
it "flushes ref caches when the task is 'gc'" do shared_examples 'flushing ref caches' do |gitaly|
expect(subject).to receive(:command).with(:gc).and_return([:the, :command]) it "flushes ref caches when the task if 'gc'" do
expect(Gitlab::Popen).to receive(:popen) expect(subject).to receive(:command).with(:gc).and_return([:the, :command])
.with([:the, :command], project.repository.path_to_repo).and_return(["", 0])
if gitaly
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect)
.and_return(nil)
else
expect(Gitlab::Popen).to receive(:popen)
.with([:the, :command], project.repository.path_to_repo).and_return(["", 0])
end
expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original
expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
expect_any_instance_of(Repository).to receive(:branch_count).and_call_original
expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
subject.perform(project.id)
end
end
context "with Gitaly turned on" do
it_should_behave_like 'flushing ref caches', true
end
context "with Gitaly turned off", skip_gitaly_mock: true do
it_should_behave_like 'flushing ref caches', false
end
expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original context "repack_full" do
expect_any_instance_of(Repository).to receive(:branch_names).and_call_original it "calls Gitaly" do
expect_any_instance_of(Repository).to receive(:branch_count).and_call_original expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:repack_full)
expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original .and_return(nil)
subject.perform(project.id) subject.perform(project.id, :full_repack)
end
end
context "repack_incremental" do
it "calls Gitaly" do
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:repack_incremental)
.and_return(nil)
subject.perform(project.id, :incremental_repack)
end
end end
shared_examples 'gc tasks' do shared_examples 'gc tasks' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment