housekeeping_service_spec.rb 3.96 KB
Newer Older
1 2 3
require 'spec_helper'

describe Projects::HousekeepingService do
4
  subject { described_class.new(project) }
5
  set(:project) { create(:project, :repository) }
6

7 8 9 10
  before do
    project.reset_pushes_since_gc
  end

11 12 13
  after do
    project.reset_pushes_since_gc
  end
14

15
  describe '#execute' do
16
    it 'enqueues a sidekiq job' do
17 18
      expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
      expect(subject).to receive(:lease_key).and_return(:the_lease_key)
19 20
      expect(subject).to receive(:task).and_return(:incremental_repack)
      expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :incremental_repack, :the_lease_key, :the_uuid).and_call_original
21

22 23 24
      Sidekiq::Testing.fake! do
        expect { subject.execute }.to change(GitGarbageCollectWorker.jobs, :size).by(1)
      end
25 26
    end

Lin Jen-Shin's avatar
Lin Jen-Shin committed
27
    it 'yields the block if given' do
28 29
      expect do |block|
        subject.execute(&block)
Lin Jen-Shin's avatar
Lin Jen-Shin committed
30 31 32
      end.to yield_with_no_args
    end

33 34 35 36 37
    it 'resets counter after execution' do
      expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
      allow(subject).to receive(:gc_period).and_return(1)
      project.increment_pushes_since_gc

38
      perform_enqueued_jobs do
39 40 41 42
        expect { subject.execute }.to change { project.pushes_since_gc }.to(0)
      end
    end

43
    context 'when no lease can be obtained' do
44
      before do
45 46
        expect(subject).to receive(:try_obtain_lease).and_return(false)
      end
47

48 49 50 51 52 53 54 55 56
      it 'does not enqueue a job' do
        expect(GitGarbageCollectWorker).not_to receive(:perform_async)

        expect { subject.execute }.to raise_error(Projects::HousekeepingService::LeaseTaken)
      end

      it 'does not reset pushes_since_gc' do
        expect do
          expect { subject.execute }.to raise_error(Projects::HousekeepingService::LeaseTaken)
57
        end.not_to change { project.pushes_since_gc }
58
      end
Lin Jen-Shin's avatar
Lin Jen-Shin committed
59 60

      it 'does not yield' do
61 62
        expect do |block|
          expect { subject.execute(&block) }
Lin Jen-Shin's avatar
Lin Jen-Shin committed
63 64 65
            .to raise_error(Projects::HousekeepingService::LeaseTaken)
        end.not_to yield_with_no_args
      end
66
    end
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

    context 'task type' do
      it 'goes through all three housekeeping tasks, executing only the highest task when there is overlap' do
        allow(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
        allow(subject).to receive(:lease_key).and_return(:the_lease_key)

        # At push 200
        expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :the_lease_key, :the_uuid)
          .exactly(1).times
        # At push 50, 100, 150
        expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :full_repack, :the_lease_key, :the_uuid)
          .exactly(3).times
        # At push 10, 20, ... (except those above)
        expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :incremental_repack, :the_lease_key, :the_uuid)
          .exactly(16).times

        201.times do
          subject.increment!
          subject.execute if subject.needed?
        end

        expect(project.pushes_since_gc).to eq(1)
      end
    end
91 92 93 94 95 96 97 98 99 100 101 102 103

    it 'runs the task specifically requested' do
      housekeeping = described_class.new(project, :gc)

      allow(housekeeping).to receive(:try_obtain_lease).and_return(:gc_uuid)
      allow(housekeeping).to receive(:lease_key).and_return(:gc_lease_key)

      expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :gc_lease_key, :gc_uuid).twice

      2.times do
        housekeeping.execute
      end
    end
104 105
  end

106
  describe '#needed?' do
107 108 109 110 111 112 113 114 115
    it 'when the count is low enough' do
      expect(subject.needed?).to eq(false)
    end

    it 'when the count is high enough' do
      allow(project).to receive(:pushes_since_gc).and_return(10)
      expect(subject.needed?).to eq(true)
    end
  end
116

117
  describe '#increment!' do
118
    it 'increments the pushes_since_gc counter' do
119
      expect { subject.increment! }.to change { project.pushes_since_gc }.by(1)
120
    end
121 122
  end
end