require 'helper' describe Delayed::Worker do describe "backend=" do before do @clazz = Class.new Delayed::Worker.backend = @clazz end after do Delayed::Worker.backend = :test end it "sets the Delayed::Job constant to the backend" do expect(Delayed::Job).to eq(@clazz) end it "sets backend with a symbol" do Delayed::Worker.backend = :test expect(Delayed::Worker.backend).to eq(Delayed::Backend::Test::Job) end end describe "job_say" do before do @worker = Delayed::Worker.new @job = double('job', :id => 123, :name => 'ExampleJob') end it "logs with job name and id" do expect(@worker).to receive(:say). with('Job ExampleJob (id=123) message', Delayed::Worker::DEFAULT_LOG_LEVEL) @worker.job_say(@job, 'message') end end context "worker read-ahead" do before do @read_ahead = Delayed::Worker.read_ahead end after do Delayed::Worker.read_ahead = @read_ahead end it "reads five jobs" do expect(Delayed::Job).to receive(:find_available).with(anything, 5, anything).and_return([]) Delayed::Job.reserve(Delayed::Worker.new) end it "reads a configurable number of jobs" do Delayed::Worker.read_ahead = 15 expect(Delayed::Job).to receive(:find_available).with(anything, Delayed::Worker.read_ahead, anything).and_return([]) Delayed::Job.reserve(Delayed::Worker.new) end end context "worker exit on complete" do before do Delayed::Worker.exit_on_complete = true end after do Delayed::Worker.exit_on_complete = false end it "exits the loop when no jobs are available" do worker = Delayed::Worker.new Timeout::timeout(2) do worker.start end end end context "worker job reservation" do before do Delayed::Worker.exit_on_complete = true end after do Delayed::Worker.exit_on_complete = false end it "handles error during job reservation" do expect(Delayed::Job).to receive(:reserve).and_raise(Exception) Delayed::Worker.new.work_off end it "gives up after 10 backend failures" do expect(Delayed::Job).to receive(:reserve).exactly(10).times.and_raise(Exception) worker = Delayed::Worker.new 9.times { worker.work_off } expect(lambda { worker.work_off }).to raise_exception Delayed::FatalBackendError end it "allows the backend to attempt recovery from reservation errors" do expect(Delayed::Job).to receive(:reserve).and_raise(Exception) expect(Delayed::Job).to receive(:recover_from).with(instance_of(Exception)) Delayed::Worker.new.work_off end end context "#say" do before(:each) do @worker = Delayed::Worker.new @worker.name = 'ExampleJob' @worker.logger = double('job') time = Time.now allow(Time).to receive(:now).and_return(time) @text = "Job executed" @worker_name = "[Worker(ExampleJob)]" @expected_time = time.strftime('%FT%T%z') end after(:each) do @worker.logger = nil end shared_examples_for "a worker which logs on the correct severity" do |severity| it "logs a message on the #{severity[:level].upcase} level given a string" do expect(@worker.logger).to receive(:send). with(severity[:level], "#{@expected_time}: #{@worker_name} #{@text}") @worker.say(@text, severity[:level]) end it "logs a message on the #{severity[:level].upcase} level given a fixnum" do expect(@worker.logger).to receive(:send). with(severity[:level], "#{@expected_time}: #{@worker_name} #{@text}") @worker.say(@text, severity[:index]) end end severities = [ { index: 0, level: "debug" }, { index: 1, level: "info" }, { index: 2, level: "warn" }, { index: 3, level: "error" }, { index: 4, level: "fatal" }, { index: 5, level: "unknown" } ] severities.each do |severity| it_behaves_like "a worker which logs on the correct severity", severity end it "logs a message on the default log's level" do expect(@worker.logger).to receive(:send). with("info", "#{@expected_time}: #{@worker_name} #{@text}") @worker.say(@text, Delayed::Worker::DEFAULT_LOG_LEVEL) end end end