From e6170287bc5839ad7fe63b571e34e06b87ee2f37 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:19:41 +0200 Subject: [PATCH 01/11] Add test for #destroy/MSJob race condition --- spec/ms_job_spec.rb | 22 ++++++++++++++++++++++ spec/spec_helper.rb | 5 +++++ spec/support/active_record_classes.rb | 2 ++ 3 files changed, 29 insertions(+) diff --git a/spec/ms_job_spec.rb b/spec/ms_job_spec.rb index 4fc4a1e3..2970e0e2 100644 --- a/spec/ms_job_spec.rb +++ b/spec/ms_job_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' RSpec.describe 'MeiliSearch::Rails::MSJob' do + include ActiveJob::TestHelper + subject(:job) { MeiliSearch::Rails::MSJob } let(:record) { double } @@ -17,4 +19,24 @@ it 'uses :meilisearch as the default queue' do expect(job.queue_name).to eq('meilisearch') end + + context 'if record is already destroyed' do + fit 'successfully deletes its document in the index' do + pollos = Restaurant.create( + name: "Los Pollos Hermanos", + kind: "Mexican", + description: "Mexican chicken restaurant in Albuquerque, New Mexico." + ) + + Restaurant.index.wait_for_task(Restaurant.index.tasks['results'].first['uid']) + expect(Restaurant.index.search("Pollos")['hits']).to be_one + + pollos.delete # does not run callbacks, unlike #destroy + + job.perform_later(pollos, :ms_remove_from_index!) + expect { perform_enqueued_jobs }.not_to raise_error + + expect(Restaurant.index.search("Pollos")['hits']).to be_empty + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6074150b..24ffc05d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -31,6 +31,11 @@ require 'active_model_serializers' require 'byebug' +# Required for running background jobs on demand (deterministically) +ActiveJob::Base.queue_adapter = :test +# Required for serializing objects in similar to production environments +GlobalID.app = "meilisearch-test" + OLD_RAILS = Gem.loaded_specs['rails'].version < Gem::Version.new('4.0') NEW_RAILS = Gem.loaded_specs['rails'].version >= Gem::Version.new('6.0') diff --git a/spec/support/active_record_classes.rb b/spec/support/active_record_classes.rb index abdbe850..11cd65a8 100644 --- a/spec/support/active_record_classes.rb +++ b/spec/support/active_record_classes.rb @@ -165,7 +165,9 @@ class Camera < Product end class Restaurant < ActiveRecord::Base + include GlobalID::Identification include MeiliSearch::Rails + meilisearch index_uid: safe_index_uid('Restaurant') do attributes_to_crop [:description] crop_length 10 From cff831a931881da3f292adaae18b9d61db3fdd2d Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:03:56 +0200 Subject: [PATCH 02/11] Add tests for record#ms_entries --- spec/integration_spec.rb | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 0b9c4f71..1cecc820 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -628,6 +628,34 @@ expect(results.size).to eq(1) end + describe '#ms_entries' do + fit 'returns all 3 indexes for a public book' do + book = Book.create!( + name: 'Frankenstein', author: 'Mary Shelley', + premium: false, released: true + ) + + expect(book.ms_entries).to contain_exactly( + a_hash_including("index_uid" => safe_index_uid('SecuredBook')), + a_hash_including("index_uid" => safe_index_uid('BookAuthor')), + a_hash_including("index_uid" => safe_index_uid('Book')), + ) + end + + fit 'returns all 3 indexes for a non-public book' do + book = Book.create!( + name: 'Frankenstein', author: 'Mary Shelley', + premium: false, released: false + ) + + expect(book.ms_entries).to contain_exactly( + a_hash_including("index_uid" => safe_index_uid('SecuredBook')), + a_hash_including("index_uid" => safe_index_uid('BookAuthor')), + a_hash_including("index_uid" => safe_index_uid('Book')), + ) + end + end + it 'returns facets using max values per facet' do 10.times do Book.create! name: Faker::Book.title, author: Faker::Book.author, genre: Faker::Book.genre @@ -1034,6 +1062,19 @@ expect(cat_index).to eq(dog_index) end + + describe '#ms_entries' do + fit 'returns the correct entry for each animal' do + toby_dog = Dog.create!(name: 'Toby the Dog') + taby_cat = Cat.create!(name: 'Taby the Cat') + + expect(toby_dog.ms_entries).to contain_exactly( + a_hash_including('primary_key' => 'dog_1')) + + expect(taby_cat.ms_entries).to contain_exactly( + a_hash_including('primary_key' => 'cat_1')) + end + end end describe 'Songs' do From 9e227d82ce814142c6254fabbbdba24c35ce0016 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:53:07 +0200 Subject: [PATCH 03/11] Move responsibility to separate job The signature of MSJob was not suitable for a fix to the race condition between MSJob and active_record#destroy. --- spec/ms_clean_up_job_spec.rb | 60 ++++++++++++++++++++++++++++++++++++ spec/ms_job_spec.rb | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 spec/ms_clean_up_job_spec.rb diff --git a/spec/ms_clean_up_job_spec.rb b/spec/ms_clean_up_job_spec.rb new file mode 100644 index 00000000..6c9fb61b --- /dev/null +++ b/spec/ms_clean_up_job_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +RSpec.describe 'MeiliSearch::Rails::MSCleanUpJob' do + include ActiveJob::TestHelper + + subject(:job) { MeiliSearch::Rails::MSCleanUpJob } + + subject(:record) do + Book.create name: "Moby Dick", author: "Herman Mellville", + premium: false, released: true + end + + let(:record_entries) do + record.ms_entries(true).each { |h| h[:index_uid] += '_test' } + end + + let(:indexes) do + %w[SecuredBook BookAuthor Book].map do |uid| + Book.index(safe_index_uid uid) + end + end + + fit 'removes record from all indexes' do + indexes.each(&:delete_all_documents) + + record + + indexes.each do |index| + index.wait_for_task(index.tasks['results'].first['uid']) + expect(index.search('*')['hits']).to be_one + end + + job.perform_now(record_entries) + + indexes.each do |index| + expect(index.search('*')['hits']).to be_empty + end + end + + context 'if record is already destroyed' do + subject!(:record) do + Restaurant.create( + name: "Los Pollos Hermanos", + kind: "Mexican", + description: "Mexican chicken restaurant in Albuquerque, New Mexico.") + end + + fit 'successfully deletes its document in the index' do + Restaurant.index.wait_for_task(Restaurant.index.tasks['results'].first['uid']) + expect(Restaurant.index.search("Pollos")['hits']).to be_one + + record.delete # does not run callbacks, unlike #destroy + + job.perform_later(record_entries) + expect { perform_enqueued_jobs }.not_to raise_error + + expect(Restaurant.index.search("Pollos")['hits']).to be_empty + end + end +end diff --git a/spec/ms_job_spec.rb b/spec/ms_job_spec.rb index 2970e0e2..f6c3113a 100644 --- a/spec/ms_job_spec.rb +++ b/spec/ms_job_spec.rb @@ -21,7 +21,7 @@ end context 'if record is already destroyed' do - fit 'successfully deletes its document in the index' do + xit 'successfully deletes its document in the index' do pollos = Restaurant.create( name: "Los Pollos Hermanos", kind: "Mexican", From 48d524b21a90ee065b1a0be5e3ad8c35401e37c8 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:07:05 +0200 Subject: [PATCH 04/11] Implement record#ms_entries method --- lib/meilisearch-rails.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/meilisearch-rails.rb b/lib/meilisearch-rails.rb index 09a240f5..43af80d3 100644 --- a/lib/meilisearch-rails.rb +++ b/lib/meilisearch-rails.rb @@ -554,6 +554,19 @@ def ms_index!(document, synchronous = false) end.compact end + def ms_entries_for(document:, synchronous:) + primary_key = ms_primary_key_of(document) + raise ArgumentError, 'Cannot index a record without a primary key' if primary_key.blank? + + ms_configurations.filter_map do |options, settings| + { + synchronous: synchronous || options[:synchronous], + index_uid: options[:index_uid], + primary_key: primary_key + }.with_indifferent_access unless ms_indexing_disabled?(options) + end + end + def ms_remove_from_index!(document, synchronous = false) return if ms_without_auto_index_scope @@ -931,6 +944,10 @@ def ms_synchronous? @ms_synchronous end + def ms_entries(synchronous = false) + self.class.ms_entries_for(document: self, synchronous: synchronous || ms_synchronous?) + end + private def ms_mark_synchronous From bd3d52500f981110073ffb6419b88bbb7336a754 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:14:34 +0200 Subject: [PATCH 05/11] Implement ms_clean_up_job --- lib/meilisearch-rails.rb | 1 + lib/meilisearch/rails/ms_clean_up_job.rb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 lib/meilisearch/rails/ms_clean_up_job.rb diff --git a/lib/meilisearch-rails.rb b/lib/meilisearch-rails.rb index 43af80d3..d9da2ae8 100644 --- a/lib/meilisearch-rails.rb +++ b/lib/meilisearch-rails.rb @@ -249,6 +249,7 @@ def additional_indexes # lazy load the ActiveJob class to ensure the # queue is initialized before using it autoload :MSJob, 'meilisearch/rails/ms_job' + autoload :MSCleanUpJob, 'meilisearch/rails/ms_clean_up_job' end # this class wraps an MeiliSearch::Index document ensuring all raised exceptions diff --git a/lib/meilisearch/rails/ms_clean_up_job.rb b/lib/meilisearch/rails/ms_clean_up_job.rb new file mode 100644 index 00000000..f52fc935 --- /dev/null +++ b/lib/meilisearch/rails/ms_clean_up_job.rb @@ -0,0 +1,19 @@ +module MeiliSearch + module Rails + class MSCleanUpJob < ::ActiveJob::Base + queue_as :meilisearch + + def perform(documents) + documents.each do |document| + index = MeiliSearch::Rails.client.index(document[:index_uid]) + + if document[:synchronous] + index.delete_document!(document[:primary_key]) + else + index.delete_document(document[:primary_key]) + end + end + end + end + end +end From fc7fe2284f4ccd8b0cc6804a4177fcb5138bb9e4 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:11:43 +0200 Subject: [PATCH 06/11] Call MSCleanUpJob from MeiliSearch::Rails --- lib/meilisearch-rails.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/meilisearch-rails.rb b/lib/meilisearch-rails.rb index d9da2ae8..acbb16b2 100644 --- a/lib/meilisearch-rails.rb +++ b/lib/meilisearch-rails.rb @@ -374,7 +374,11 @@ def meilisearch(options = {}, &block) proc = if options[:enqueue] == true proc do |record, remove| - MSJob.perform_later(record, remove ? 'ms_remove_from_index!' : 'ms_index!') + if remove + MSCleanUpJob.perform_later(record.ms_entries) + else + MSJob.perform_later(record, 'ms_index!') + end end elsif options[:enqueue].respond_to?(:call) options[:enqueue] @@ -446,7 +450,7 @@ def meilisearch(options = {}, &block) end end elsif respond_to?(:after_destroy) - after_destroy { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) } + after_destroy_commit { |searchable| searchable.ms_enqueue_remove_from_index!(ms_synchronous?) } end end From cd7fb157d7d12cb78cc4a74b2635ae0c37fe8ded Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:12:24 +0200 Subject: [PATCH 07/11] Fix regressions in tests --- spec/integration_spec.rb | 17 ++++++++++------- spec/ms_clean_up_job_spec.rb | 11 ++++++----- spec/ms_job_spec.rb | 20 -------------------- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 1cecc820..3ef31313 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -629,7 +629,7 @@ end describe '#ms_entries' do - fit 'returns all 3 indexes for a public book' do + it 'returns all 3 indexes for a public book' do book = Book.create!( name: 'Frankenstein', author: 'Mary Shelley', premium: false, released: true @@ -642,7 +642,7 @@ ) end - fit 'returns all 3 indexes for a non-public book' do + it 'returns all 3 indexes for a non-public book' do book = Book.create!( name: 'Frankenstein', author: 'Mary Shelley', premium: false, released: false @@ -945,7 +945,10 @@ end describe 'ConditionallyEnqueuedDocument' do - before { allow(MeiliSearch::Rails::MSJob).to receive(:perform_later).and_return(nil) } + before do + allow(MeiliSearch::Rails::MSJob).to receive(:perform_later).and_return(nil) + allow(MeiliSearch::Rails::MSCleanUpJob).to receive(:perform_later).and_return(nil) + end it 'does not try to enqueue an index job when :if option resolves to false' do doc = ConditionallyEnqueuedDocument.create! name: 'test', is_public: false @@ -965,7 +968,7 @@ doc.destroy! - expect(MeiliSearch::Rails::MSJob).to have_received(:perform_later).with(doc, 'ms_remove_from_index!') + expect(MeiliSearch::Rails::MSCleanUpJob).to have_received(:perform_later).with(doc.ms_entries) end end end @@ -1064,15 +1067,15 @@ end describe '#ms_entries' do - fit 'returns the correct entry for each animal' do + it 'returns the correct entry for each animal' do toby_dog = Dog.create!(name: 'Toby the Dog') taby_cat = Cat.create!(name: 'Taby the Cat') expect(toby_dog.ms_entries).to contain_exactly( - a_hash_including('primary_key' => 'dog_1')) + a_hash_including('primary_key' => /dog_\d+/)) expect(taby_cat.ms_entries).to contain_exactly( - a_hash_including('primary_key' => 'cat_1')) + a_hash_including('primary_key' => /cat_\d+/)) end end end diff --git a/spec/ms_clean_up_job_spec.rb b/spec/ms_clean_up_job_spec.rb index 6c9fb61b..3124de7f 100644 --- a/spec/ms_clean_up_job_spec.rb +++ b/spec/ms_clean_up_job_spec.rb @@ -20,7 +20,7 @@ end end - fit 'removes record from all indexes' do + it 'removes record from all indexes' do indexes.each(&:delete_all_documents) record @@ -37,21 +37,22 @@ end end - context 'if record is already destroyed' do - subject!(:record) do + context 'when record is already destroyed' do + subject(:record) do Restaurant.create( name: "Los Pollos Hermanos", kind: "Mexican", description: "Mexican chicken restaurant in Albuquerque, New Mexico.") end - fit 'successfully deletes its document in the index' do + it 'successfully deletes its document in the index' do + record Restaurant.index.wait_for_task(Restaurant.index.tasks['results'].first['uid']) expect(Restaurant.index.search("Pollos")['hits']).to be_one record.delete # does not run callbacks, unlike #destroy - job.perform_later(record_entries) + job.perform_later(record.ms_entries(true)) expect { perform_enqueued_jobs }.not_to raise_error expect(Restaurant.index.search("Pollos")['hits']).to be_empty diff --git a/spec/ms_job_spec.rb b/spec/ms_job_spec.rb index f6c3113a..12dc33f7 100644 --- a/spec/ms_job_spec.rb +++ b/spec/ms_job_spec.rb @@ -19,24 +19,4 @@ it 'uses :meilisearch as the default queue' do expect(job.queue_name).to eq('meilisearch') end - - context 'if record is already destroyed' do - xit 'successfully deletes its document in the index' do - pollos = Restaurant.create( - name: "Los Pollos Hermanos", - kind: "Mexican", - description: "Mexican chicken restaurant in Albuquerque, New Mexico." - ) - - Restaurant.index.wait_for_task(Restaurant.index.tasks['results'].first['uid']) - expect(Restaurant.index.search("Pollos")['hits']).to be_one - - pollos.delete # does not run callbacks, unlike #destroy - - job.perform_later(pollos, :ms_remove_from_index!) - expect { perform_enqueued_jobs }.not_to raise_error - - expect(Restaurant.index.search("Pollos")['hits']).to be_empty - end - end end From 6cbd82428bb14a469a98cb93bd13c05fbd684d70 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:12:15 +0100 Subject: [PATCH 08/11] Fix rubocop offenses --- .rubocop_todo.yml | 73 ++++++++++++++++++++++++++++++++++++++------- spec/spec_helper.rb | 2 +- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d580b66e..8560fb10 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2023-11-06 11:54:44 UTC using RuboCop version 1.27.0. +# on 2024-01-10 10:49:28 UTC using RuboCop version 1.27.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -30,6 +30,15 @@ Layout/EmptyLinesAroundModuleBody: Exclude: - 'lib/meilisearch-rails.rb' +# Offense count: 3 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineMethodCallBraceLayout: + Exclude: + - 'spec/integration_spec.rb' + - 'spec/ms_clean_up_job_spec.rb' + # Offense count: 1 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -44,6 +53,13 @@ Lint/SuppressedException: Exclude: - 'lib/meilisearch-rails.rb' +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. +Lint/UnusedBlockArgument: + Exclude: + - 'lib/meilisearch-rails.rb' + # Offense count: 2 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. @@ -54,7 +70,7 @@ Lint/UnusedMethodArgument: # Offense count: 11 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: - Max: 102 + Max: 104 # Offense count: 1 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. @@ -75,17 +91,17 @@ Metrics/CyclomaticComplexity: # Offense count: 16 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: - Max: 99 + Max: 103 # Offense count: 1 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 435 + Max: 449 # Offense count: 8 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: - Max: 33 + Max: 34 # Offense count: 1 Naming/AccessorMethodName: @@ -107,7 +123,7 @@ Naming/MethodParameterName: Exclude: - 'lib/meilisearch-rails.rb' -# Offense count: 15 +# Offense count: 20 RSpec/BeforeAfterAll: Exclude: - 'spec/integration_spec.rb' @@ -118,7 +134,7 @@ RSpec/DescribeClass: Exclude: - 'spec/integration_spec.rb' -# Offense count: 37 +# Offense count: 46 # Configuration parameters: CountAsOne. RSpec/ExampleLength: Max: 19 @@ -132,7 +148,7 @@ RSpec/FilePath: - 'spec/settings_spec.rb' - 'spec/utilities_spec.rb' -# Offense count: 26 +# Offense count: 25 # Configuration parameters: AssignmentOnly. RSpec/InstanceVariable: Exclude: @@ -150,6 +166,12 @@ RSpec/MultipleDescribes: Exclude: - 'spec/integration_spec.rb' +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +RSpec/MultipleSubjects: + Exclude: + - 'spec/ms_clean_up_job_spec.rb' + # Offense count: 1 # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: @@ -188,14 +210,45 @@ Style/InverseMethods: Exclude: - 'lib/meilisearch-rails.rb' -# Offense count: 8 +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Style/MultilineIfModifier: + Exclude: + - 'lib/meilisearch-rails.rb' + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: AllowedMethods. +# AllowedMethods: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with +Style/NestedParenthesizedCalls: + Exclude: + - 'spec/ms_clean_up_job_spec.rb' + +# Offense count: 9 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - 'lib/meilisearch-rails.rb' -# Offense count: 20 +# Offense count: 13 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'spec/integration_spec.rb' + - 'spec/ms_clean_up_job_spec.rb' + +# Offense count: 2 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArguments: + Exclude: + - 'spec/integration_spec.rb' + +# Offense count: 19 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 24ffc05d..0683e8eb 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -34,7 +34,7 @@ # Required for running background jobs on demand (deterministically) ActiveJob::Base.queue_adapter = :test # Required for serializing objects in similar to production environments -GlobalID.app = "meilisearch-test" +GlobalID.app = 'meilisearch-test' OLD_RAILS = Gem.loaded_specs['rails'].version < Gem::Version.new('4.0') NEW_RAILS = Gem.loaded_specs['rails'].version >= Gem::Version.new('6.0') From b61c332c85eaeced86596be8501d19a2f8b04af7 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Wed, 29 Nov 2023 11:16:42 +0100 Subject: [PATCH 09/11] Fix already destroyed callback spec --- spec/ms_clean_up_job_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/ms_clean_up_job_spec.rb b/spec/ms_clean_up_job_spec.rb index 3124de7f..7c6d10f6 100644 --- a/spec/ms_clean_up_job_spec.rb +++ b/spec/ms_clean_up_job_spec.rb @@ -52,7 +52,7 @@ record.delete # does not run callbacks, unlike #destroy - job.perform_later(record.ms_entries(true)) + job.perform_later(record_entries) expect { perform_enqueued_jobs }.not_to raise_error expect(Restaurant.index.search("Pollos")['hits']).to be_empty From 083d1e2da205acf6c2d95c0e7b9500bbcb2629f4 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Wed, 29 Nov 2023 11:17:05 +0100 Subject: [PATCH 10/11] Fix indexes name conflict in specs --- spec/support/2_method_helpers.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/support/2_method_helpers.rb b/spec/support/2_method_helpers.rb index 4f8e4997..e8aa332f 100644 --- a/spec/support/2_method_helpers.rb +++ b/spec/support/2_method_helpers.rb @@ -1,16 +1,16 @@ # A unique prefix for your test run in local or CI SAFE_INDEX_PREFIX = "rails_#{SecureRandom.hex(8)}".freeze -def indexes +def _indexes @indexes ||= {} end # avoid concurrent access to the same index in local or CI def safe_index_uid(name) - indexes[name] ||= "#{SAFE_INDEX_PREFIX}_#{name}" + _indexes[name] ||= "#{SAFE_INDEX_PREFIX}_#{name}" end # get a list of safe indexes in local or CI def safe_index_list - indexes.values.flat_map { |safe_idx| [safe_idx, "#{safe_idx}_test"] } + _indexes.values.flat_map { |safe_idx| [safe_idx, "#{safe_idx}_test"] } end From 91437f1430909381487c0c9c088db42aba8c4c11 Mon Sep 17 00:00:00 2001 From: ellnix <103502144+ellnix@users.noreply.github.com> Date: Wed, 10 Jan 2024 11:47:27 +0100 Subject: [PATCH 11/11] Refactor CleanUpJob spec for clarity --- spec/ms_clean_up_job_spec.rb | 41 +++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/spec/ms_clean_up_job_spec.rb b/spec/ms_clean_up_job_spec.rb index 7c6d10f6..ccbf687c 100644 --- a/spec/ms_clean_up_job_spec.rb +++ b/spec/ms_clean_up_job_spec.rb @@ -3,9 +3,21 @@ RSpec.describe 'MeiliSearch::Rails::MSCleanUpJob' do include ActiveJob::TestHelper - subject(:job) { MeiliSearch::Rails::MSCleanUpJob } + def clean_up_indexes + indexes.each(&:delete_all_documents) + end + + def create_indexed_record + record + + indexes.each do |index| + index.wait_for_task(index.tasks['results'].last['uid']) + end + end - subject(:record) do + subject(:clean_up) { MeiliSearch::Rails::MSCleanUpJob } + + let(:record) do Book.create name: "Moby Dick", author: "Herman Mellville", premium: false, released: true end @@ -21,16 +33,11 @@ end it 'removes record from all indexes' do - indexes.each(&:delete_all_documents) - - record + clean_up_indexes - indexes.each do |index| - index.wait_for_task(index.tasks['results'].first['uid']) - expect(index.search('*')['hits']).to be_one - end + create_indexed_record - job.perform_now(record_entries) + clean_up.perform_now(record_entries) indexes.each do |index| expect(index.search('*')['hits']).to be_empty @@ -45,17 +52,21 @@ description: "Mexican chicken restaurant in Albuquerque, New Mexico.") end + let(:indexes) { [Restaurant.index] } + it 'successfully deletes its document in the index' do - record - Restaurant.index.wait_for_task(Restaurant.index.tasks['results'].first['uid']) - expect(Restaurant.index.search("Pollos")['hits']).to be_one + clean_up_indexes + + create_indexed_record record.delete # does not run callbacks, unlike #destroy - job.perform_later(record_entries) + clean_up.perform_later(record_entries) expect { perform_enqueued_jobs }.not_to raise_error - expect(Restaurant.index.search("Pollos")['hits']).to be_empty + indexes.each do |index| + expect(index.search('*')['hits']).to be_empty + end end end end