require "spec_helper" describe AsyncIndexer do include ActiveJob::TestHelper def queue_adapter_for_test ActiveJob::QueueAdapters::TestAdapter.new end it "enqueues IDs" do freeze_time batch_key = "WorkIndexer:34:#{Time.now.to_i}" expect do AsyncIndexer.index(Work, [34], :background) end.to enqueue_job.on_queue("reindex_low").with(batch_key) expect(AsyncIndexer::REDIS.smembers(batch_key)).to contain_exactly("34") end context "when persistent indexing failures occur" do let(:work_id) { create(:work).id } before do # Make batch indexing always fail. allow($elasticsearch).to receive(:bulk) do |options| { "errors" => true, "items" => options[:body].map do |line| action = line.keys.first next unless (id = line[action]["_id"]) { action.to_s => { "_id" => id, "error" => { "an error" => "with a message" } } } end.compact } end end it "tries indexing IDs up to 3 times" do expect(BookmarkedWorkIndexer).to receive(:new).with([work_id.to_s]) .exactly(3).times .and_call_original expect do AsyncIndexer.index(BookmarkedWorkIndexer, [work_id], :main) end.to enqueue_job 2.times do # Batch keys in Redis contain a timestamp. Ensure that each retry has # a different batch key. travel(1.second) expect { perform_enqueued_jobs } .to enqueue_job.on_queue("reindex_failures") end # The third failure does not enqueue a retry. travel(1.second) expect { perform_enqueued_jobs } .not_to enqueue_job end end context "when there are no IDs to index" do it "doesn't call the indexer" do expect(AsyncIndexer::REDIS).to receive(:smembers).and_return([]) expect(WorkIndexer).not_to receive(:new) AsyncIndexer.index(WorkIndexer, [34], :main) perform_enqueued_jobs end end end