spec/base_spec.rb in wayfarer-0.4.6 vs spec/base_spec.rb in wayfarer-0.4.7
- old
+ new
@@ -1,224 +1,204 @@
# frozen_string_literal: true
require "spec_helpers"
describe Wayfarer::Base, redis: true do
- include Wayfarer::Redis::Connection
+ let(:task) { build(:task, :redis_pool) }
- let(:url) { "https://example.com" }
- let(:batch) { "batch" }
- let(:task) { build(:task, batch: batch, url: url) }
- let(:klass) { Class.new(Wayfarer::Base) }
+ before do
+ stub_const("DummyJob", Class.new(ActiveJob::Base).include(Wayfarer::Base))
+ end
- before { stub_const("DummyJob", klass) }
-
describe "::crawl" do
it "enqueues a task" do
expect(DummyJob).to receive(:perform_later).with(task)
- DummyJob.crawl(url, batch: batch)
+ DummyJob.crawl(task.url, batch: task.batch)
end
it "returns a task" do
- expect(DummyJob.crawl(url)).to be_a(Wayfarer::Task)
+ expect(DummyJob.crawl(task.url)).to be_a(Wayfarer::Task)
end
end
- describe "Callbacks" do
- let(:counter) { task.counter }
+ describe "#perform" do
+ subject(:counter) { Wayfarer::Redis::Counter.new(task) }
+ let!(:initial) { counter.increment }
- describe "after enqueue" do
- it "increments the counter" do
- expect {
- DummyJob.crawl(url, batch: batch)
- }.to change { counter.value }.by(1)
+ before do
+ DummyJob.class_eval do
+ route.to :index
end
end
- describe "after perform" do
- it "decrements the counter" do
- DummyJob.crawl(url, batch: batch)
- task.counter.increment
- expect { perform_enqueued_jobs }.to change { task.counter.value }.by(-1)
+ describe "succeeding job" do
+ before do
+ DummyJob.class_eval do
+ def index; end
+ end
end
- context "when counter reaches 0" do
- it "resets the barrier" do
- DummyJob.crawl(url, batch: batch)
- perform_enqueued_jobs
- redis do |conn|
- expect(conn.exists?(task.barrier.redis_key)).to be(false)
- end
- end
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
- it "resets the counter" do
- DummyJob.crawl(url, batch: batch)
+ expect {
+ DummyJob.perform_later(task)
perform_enqueued_jobs
- redis do |conn|
- expect(conn.exists?(task.counter.redis_key)).to be(false)
- end
- end
-
- it "runs after batch callbacks" do
- expect { |spy|
- klass.after_batch(&spy)
- DummyJob.crawl(url, batch: batch)
- perform_enqueued_jobs
- }.to yield_control
- end
+ assert_performed_jobs 1
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
end
end
- end
- describe "Unhandled exceptions" do
- let(:klass) { Class.new(Wayfarer::Base) }
-
- before do
- allow_any_instance_of(DummyJob).to receive(:perform).and_raise(RuntimeError.new)
- end
-
- it "does not retry the job" do
- DummyJob.crawl(url, batch: batch)
-
- expect {
- begin
- perform_enqueued_jobs
- rescue StandardError
- nil
+ describe "failing job" do
+ before do
+ DummyJob.class_eval do
+ def index
+ raise
+ end
end
- }.to change { enqueued_jobs.size }.by(-1)
- end
+ end
- it "decrements the counter" do
- 3.times { task.counter.increment }
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
- DummyJob.crawl(url, batch: batch)
- begin
- perform_enqueued_jobs
- rescue StandardError
- nil
+ expect {
+ DummyJob.perform_later(task)
+ expect { perform_enqueued_jobs }.to raise_error(RuntimeError)
+ assert_performed_jobs 1
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
end
-
- expect(task.counter.value).to be(3)
end
- end
- describe "Retries" do
- let(:klass) do
- Class.new(Wayfarer::Base) do
- retry_on RuntimeError, attempts: 3 do |job, error|
- Spy.call(job, error)
+ describe "failing job with retries" do
+ before do
+ DummyJob.class_eval do
+ retry_on StandardError, attempts: 3
+
+ def index
+ raise
+ end
end
end
- end
- before do
- allow_any_instance_of(DummyJob).to receive(:perform) do |job|
- task = job.arguments.first
- task.metadata.job = job
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
- raise RuntimeError
+ expect {
+ DummyJob.perform_later(task)
+ 2.times { perform_enqueued_jobs }
+ expect { perform_enqueued_jobs }.to raise_error(RuntimeError)
+ assert_performed_jobs 3
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
end
-
- stub_const("Spy", spy)
end
- it "retries the job" do
- expect(Spy).to receive(:call).exactly(:once)
- .with(kind_of(DummyJob),
- kind_of(RuntimeError))
+ describe "discarded after retries" do
+ before do
+ DummyJob.class_eval do
+ ErrorA = Class.new(StandardError)
+ ErrorB = Class.new(StandardError)
- DummyJob.crawl(url, batch: batch)
+ retry_on ErrorA, attempts: 5
- expect {
- perform_enqueued_jobs
- }.to change { enqueued_jobs.last["executions"] }.by(1)
+ discard_on ErrorB
- expect {
- perform_enqueued_jobs
- }.to change { enqueued_jobs.last["executions"] }.by(1)
+ def index
+ raise ErrorB if executions == 5
- expect {
- perform_enqueued_jobs
- }.to change { enqueued_jobs.size }.by(-1)
- end
+ raise ErrorA
+ end
+ end
+ end
- it "marks the URL seen" do
- task.counter.increment # otherwise barrier gets reset
- DummyJob.crawl(url, batch: batch)
- 3.times { perform_enqueued_jobs }
- expect(task.barrier.seen?(task.url)).to be(true)
- end
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
- it "decrements the counter" do
- 3.times { task.counter.increment }
-
- DummyJob.crawl(url, batch: batch)
- 3.times { perform_enqueued_jobs }
-
- expect(task.counter.value).to be(3)
+ expect {
+ DummyJob.perform_later(task)
+ 4.times { perform_enqueued_jobs }
+ perform_enqueued_jobs
+ assert_performed_jobs 5
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
+ end
end
- it "runs after batch callbacks" do
- expect { |spy|
- klass.after_batch(&spy)
- DummyJob.crawl(url, batch: batch)
- 3.times { perform_enqueued_jobs }
- }.to yield_control
- end
- end
+ describe "discarded job" do
+ before do
+ DummyJob.class_eval do
+ discard_on RuntimeError
- describe "Discarding" do
- let(:klass) do
- Class.new(Wayfarer::Base) do
- discard_on RuntimeError do |job, error|
- Spy.call(job, error)
+ def index
+ raise "boom"
+ end
end
end
- end
- before do
- allow_any_instance_of(DummyJob).to receive(:perform) do |job|
- task = job.arguments.first
- task.metadata.job = job
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
- raise RuntimeError
+ expect {
+ DummyJob.perform_later(task)
+ perform_enqueued_jobs
+ assert_performed_jobs 1
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
end
-
- stub_const("Spy", spy)
end
- it "discards the job" do
- expect(Spy).to receive(:call).exactly(:once)
- .with(kind_of(DummyJob),
- kind_of(RuntimeError))
+ describe "after_batch callback" do
+ let(:initial) { counter.value }
- DummyJob.crawl(url, batch: batch)
+ describe "when after_perform callback fails" do
+ before do
+ DummyJob.class_eval do
+ after_perform { raise }
- expect {
- perform_enqueued_jobs
- }.to change { enqueued_jobs.size }.by(-1)
- end
+ def index; end
+ end
+ end
- it "marks the URL seen" do
- task.counter.increment # otherwise barrier gets reset
- DummyJob.crawl(url, batch: batch)
- perform_enqueued_jobs
- expect(task.barrier.seen?(task.url)).to be(true)
- end
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
- it "decrements the counter" do
- 3.times { task.counter.increment }
- DummyJob.crawl(url, batch: batch)
- perform_enqueued_jobs
- expect(task.counter.value).to be(3)
- end
+ expect {
+ DummyJob.perform_later(task)
+ expect { perform_enqueued_jobs }.to raise_error(RuntimeError)
+ assert_performed_jobs 1
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
+ end
+ end
- it "runs after batch callbacks" do
- expect { |spy|
- klass.after_batch(&spy)
- DummyJob.crawl(url, batch: batch)
- perform_enqueued_jobs
- }.to yield_control
+ describe "when after_batch callback fails" do
+ before do
+ DummyJob.class_eval do
+ after_batch { raise }
+
+ def index; end
+ end
+ end
+
+ specify do
+ expect_any_instance_of(Wayfarer::Redis::Counter)
+ .to receive(:increment).at_least(:once).and_call_original
+
+ expect {
+ DummyJob.perform_later(task)
+ expect { perform_enqueued_jobs }.to raise_error(RuntimeError)
+ assert_performed_jobs 1
+ expect(enqueued_jobs).to be_empty
+ }.not_to change { counter.value }.from(initial)
+ end
+ end
end
end
end