require 'job_uniqueness/spec_helper' RSpec.describe CanvasSync::JobUniqueness::OnConflict::Reschedule do include_context "on_conflict specs" include_examples "OnConflict is compatible with", %i[while_executing] it "calls reenqueue" do expect(lock_context).to receive(:reenqueue) do |*args, **kwargs| expect(Thread.current[:unique_jobs_previous_context]).to be_present end on_conflict.call end it "reschedules successfully" do TestWorker.unique_job_options.merge!({ strategy: :until_and_while_executing, on_conflict: { enqueue: :raise, perform: :reschedule }}) lock_context.handle_lifecycle!(:enqueue) {} lock_context.handle_lifecycle!(:perform) {} lock_context2 = CanvasSync::JobUniqueness::Compat::Sidekiq::SidekiqLockContext.new({ jid: 'j2', queue: 'default', job_clazz: 'TestWorker'}, job_instance: {}) lock_context2.handle_lifecycle!(:enqueue) {} lock_context2.handle_lifecycle!(:perform) {} end it "maintains a consistent lock_id" do TestWorker.clear TestWorker.unique_job_options.merge!({ strategy: :while_executing, on_conflict: :reschedule }) lock_context.handle_lifecycle!(:enqueue) {} lock_context.handle_lifecycle!(:perform) {} TestWorker.perform_async j1 = TestWorker.jobs[0] TestWorker.perform_one j2 = TestWorker.jobs[0] expect(j1).not_to eq(j2) expect(j1['uniqueness_cache_data']['lid']).to be_present expect(j1['uniqueness_cache_data']['lid']).to eq(j2['uniqueness_cache_data']['lid']) end it "unlocks after rescheduling" do TestWorker.clear TestWorker.unique_job_options.merge!({ strategy: :while_executing, on_conflict: :reschedule }) lock_context.handle_lifecycle!(:enqueue) {} lock_context.handle_lifecycle!(:perform) {} TestWorker.perform_async expect(TestWorker.jobs.size).to eq(1) TestWorker.perform_one expect(TestWorker.jobs.size).to eq(1) lock_context.lock_strategy.send(:unlock) Sidekiq::Worker.drain_all expect(TestWorker.jobs.size).to eq(0) # Run another worker to validate that the lock was released TestWorker.perform_async TestWorker.perform_one expect(TestWorker.jobs.size).to eq(0) end end