housekeeping_service_spec.rb 3.53 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

Yorick Peterse's avatar
Yorick Peterse committed
11 12 13
  after do
    project.reset_pushes_since_gc
  end
14

Yorick Peterse's avatar
Yorick Peterse committed
15
  describe '#execute' do
16
    it 'enqueues a sidekiq job' do
Jacob Vosmaer's avatar
Jacob Vosmaer committed
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
Lin Jen-Shin's avatar
Lin Jen-Shin committed
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)
Yorick Peterse's avatar
Yorick Peterse committed
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
Lin Jen-Shin's avatar
Lin Jen-Shin committed
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
  end

Yorick Peterse's avatar
Yorick Peterse committed
93
  describe '#needed?' do
94 95 96 97 98 99 100 101 102
    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
Jacob Vosmaer's avatar
Jacob Vosmaer committed
103

Yorick Peterse's avatar
Yorick Peterse committed
104
  describe '#increment!' do
Jacob Vosmaer's avatar
Jacob Vosmaer committed
105
    it 'increments the pushes_since_gc counter' do
106
      expect { subject.increment! }.to change { project.pushes_since_gc }.by(1)
107
    end
Jacob Vosmaer's avatar
Jacob Vosmaer committed
108 109
  end
end