chewy 8.0.0 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +30 -16
  4. data/lib/chewy/errors.rb +3 -0
  5. data/lib/chewy/fields/root.rb +3 -3
  6. data/lib/chewy/index/crutch.rb +12 -2
  7. data/lib/chewy/index/import/bulk_builder.rb +4 -3
  8. data/lib/chewy/index/import/routine.rb +2 -1
  9. data/lib/chewy/index/import.rb +4 -4
  10. data/lib/chewy/index/witchcraft.rb +24 -8
  11. data/lib/chewy/multi_search.rb +1 -1
  12. data/lib/chewy/search/parameters/runtime_mappings.rb +14 -0
  13. data/lib/chewy/search/request.rb +18 -2
  14. data/lib/chewy/search/scrolling.rb +14 -6
  15. data/lib/chewy/stash.rb +10 -6
  16. data/lib/chewy/version.rb +1 -1
  17. metadata +5 -131
  18. data/.github/CODEOWNERS +0 -1
  19. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -39
  20. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  21. data/.github/PULL_REQUEST_TEMPLATE.md +0 -16
  22. data/.github/dependabot.yml +0 -42
  23. data/.github/workflows/ruby.yml +0 -61
  24. data/.gitignore +0 -22
  25. data/.rspec +0 -2
  26. data/.rubocop.yml +0 -64
  27. data/.rubocop_todo.yml +0 -225
  28. data/.yardopts +0 -5
  29. data/CODE_OF_CONDUCT.md +0 -14
  30. data/CONTRIBUTING.md +0 -63
  31. data/Gemfile +0 -22
  32. data/Guardfile +0 -25
  33. data/Rakefile +0 -17
  34. data/chewy.gemspec +0 -24
  35. data/docker-compose.yml +0 -14
  36. data/docs/README.md +0 -16
  37. data/docs/configuration.md +0 -440
  38. data/docs/import.md +0 -122
  39. data/docs/indexing.md +0 -329
  40. data/docs/querying.md +0 -72
  41. data/docs/rake_tasks.md +0 -108
  42. data/docs/testing.md +0 -41
  43. data/docs/troubleshooting.md +0 -101
  44. data/filters +0 -78
  45. data/gemfiles/base.gemfile +0 -12
  46. data/gemfiles/rails.7.2.activerecord.gemfile +0 -14
  47. data/gemfiles/rails.8.0.activerecord.gemfile +0 -14
  48. data/migration_guide.md +0 -56
  49. data/spec/chewy/config_spec.rb +0 -110
  50. data/spec/chewy/elastic_client_spec.rb +0 -26
  51. data/spec/chewy/fields/base_spec.rb +0 -700
  52. data/spec/chewy/fields/root_spec.rb +0 -142
  53. data/spec/chewy/fields/time_fields_spec.rb +0 -28
  54. data/spec/chewy/index/actions_spec.rb +0 -851
  55. data/spec/chewy/index/adapter/active_record_spec.rb +0 -663
  56. data/spec/chewy/index/adapter/object_spec.rb +0 -243
  57. data/spec/chewy/index/aliases_spec.rb +0 -49
  58. data/spec/chewy/index/import/bulk_builder_spec.rb +0 -494
  59. data/spec/chewy/index/import/bulk_request_spec.rb +0 -95
  60. data/spec/chewy/index/import/journal_builder_spec.rb +0 -87
  61. data/spec/chewy/index/import/routine_spec.rb +0 -110
  62. data/spec/chewy/index/import_spec.rb +0 -615
  63. data/spec/chewy/index/mapping_spec.rb +0 -135
  64. data/spec/chewy/index/observe/active_record_methods_spec.rb +0 -68
  65. data/spec/chewy/index/observe/callback_spec.rb +0 -139
  66. data/spec/chewy/index/observe_spec.rb +0 -143
  67. data/spec/chewy/index/settings_spec.rb +0 -136
  68. data/spec/chewy/index/specification_spec.rb +0 -156
  69. data/spec/chewy/index/syncer_spec.rb +0 -118
  70. data/spec/chewy/index/witchcraft_spec.rb +0 -245
  71. data/spec/chewy/index/wrapper_spec.rb +0 -100
  72. data/spec/chewy/index_spec.rb +0 -269
  73. data/spec/chewy/journal_spec.rb +0 -223
  74. data/spec/chewy/minitest/helpers_spec.rb +0 -194
  75. data/spec/chewy/minitest/search_index_receiver_spec.rb +0 -120
  76. data/spec/chewy/multi_search_spec.rb +0 -84
  77. data/spec/chewy/rake_helper_spec.rb +0 -656
  78. data/spec/chewy/repository_spec.rb +0 -50
  79. data/spec/chewy/rspec/build_query_spec.rb +0 -34
  80. data/spec/chewy/rspec/helpers_spec.rb +0 -61
  81. data/spec/chewy/rspec/update_index_spec.rb +0 -313
  82. data/spec/chewy/runtime/version_spec.rb +0 -48
  83. data/spec/chewy/runtime_spec.rb +0 -9
  84. data/spec/chewy/search/loader_spec.rb +0 -83
  85. data/spec/chewy/search/pagination/kaminari_examples.rb +0 -69
  86. data/spec/chewy/search/pagination/kaminari_spec.rb +0 -21
  87. data/spec/chewy/search/parameters/aggs_spec.rb +0 -5
  88. data/spec/chewy/search/parameters/bool_storage_examples.rb +0 -53
  89. data/spec/chewy/search/parameters/collapse_spec.rb +0 -5
  90. data/spec/chewy/search/parameters/docvalue_fields_spec.rb +0 -5
  91. data/spec/chewy/search/parameters/explain_spec.rb +0 -5
  92. data/spec/chewy/search/parameters/filter_spec.rb +0 -5
  93. data/spec/chewy/search/parameters/hash_storage_examples.rb +0 -59
  94. data/spec/chewy/search/parameters/highlight_spec.rb +0 -5
  95. data/spec/chewy/search/parameters/ignore_unavailable_spec.rb +0 -67
  96. data/spec/chewy/search/parameters/indices_spec.rb +0 -99
  97. data/spec/chewy/search/parameters/integer_storage_examples.rb +0 -32
  98. data/spec/chewy/search/parameters/knn_spec.rb +0 -5
  99. data/spec/chewy/search/parameters/limit_spec.rb +0 -5
  100. data/spec/chewy/search/parameters/load_spec.rb +0 -60
  101. data/spec/chewy/search/parameters/min_score_spec.rb +0 -32
  102. data/spec/chewy/search/parameters/none_spec.rb +0 -5
  103. data/spec/chewy/search/parameters/offset_spec.rb +0 -5
  104. data/spec/chewy/search/parameters/order_spec.rb +0 -72
  105. data/spec/chewy/search/parameters/post_filter_spec.rb +0 -5
  106. data/spec/chewy/search/parameters/preference_spec.rb +0 -5
  107. data/spec/chewy/search/parameters/profile_spec.rb +0 -5
  108. data/spec/chewy/search/parameters/query_spec.rb +0 -5
  109. data/spec/chewy/search/parameters/query_storage_examples.rb +0 -434
  110. data/spec/chewy/search/parameters/request_cache_spec.rb +0 -67
  111. data/spec/chewy/search/parameters/rescore_spec.rb +0 -62
  112. data/spec/chewy/search/parameters/script_fields_spec.rb +0 -5
  113. data/spec/chewy/search/parameters/search_after_spec.rb +0 -35
  114. data/spec/chewy/search/parameters/search_type_spec.rb +0 -5
  115. data/spec/chewy/search/parameters/source_spec.rb +0 -162
  116. data/spec/chewy/search/parameters/storage_spec.rb +0 -60
  117. data/spec/chewy/search/parameters/stored_fields_spec.rb +0 -126
  118. data/spec/chewy/search/parameters/string_array_storage_examples.rb +0 -63
  119. data/spec/chewy/search/parameters/string_storage_examples.rb +0 -32
  120. data/spec/chewy/search/parameters/suggest_spec.rb +0 -5
  121. data/spec/chewy/search/parameters/terminate_after_spec.rb +0 -5
  122. data/spec/chewy/search/parameters/timeout_spec.rb +0 -5
  123. data/spec/chewy/search/parameters/track_scores_spec.rb +0 -5
  124. data/spec/chewy/search/parameters/track_total_hits_spec.rb +0 -5
  125. data/spec/chewy/search/parameters/version_spec.rb +0 -5
  126. data/spec/chewy/search/parameters_spec.rb +0 -161
  127. data/spec/chewy/search/query_proxy_spec.rb +0 -95
  128. data/spec/chewy/search/request_spec.rb +0 -886
  129. data/spec/chewy/search/response_spec.rb +0 -180
  130. data/spec/chewy/search/scrolling_spec.rb +0 -171
  131. data/spec/chewy/search_spec.rb +0 -127
  132. data/spec/chewy/stash_spec.rb +0 -85
  133. data/spec/chewy/strategy/active_job_spec.rb +0 -73
  134. data/spec/chewy/strategy/atomic_no_refresh_spec.rb +0 -60
  135. data/spec/chewy/strategy/atomic_spec.rb +0 -61
  136. data/spec/chewy/strategy/delayed_sidekiq_spec.rb +0 -225
  137. data/spec/chewy/strategy/lazy_sidekiq_spec.rb +0 -214
  138. data/spec/chewy/strategy/sidekiq_spec.rb +0 -52
  139. data/spec/chewy/strategy_spec.rb +0 -125
  140. data/spec/chewy_spec.rb +0 -100
  141. data/spec/spec_helper.rb +0 -69
  142. data/spec/support/active_record.rb +0 -124
  143. data/spec/support/class_helpers.rb +0 -16
  144. data/spec/support/fail_helpers.rb +0 -13
@@ -1,269 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Chewy::Index do
4
- before do
5
- stub_index(:dummies)
6
- end
7
-
8
- describe '.import', :orm do
9
- before do
10
- stub_model(:city)
11
- stub_model(:country)
12
-
13
- stub_index(:cities) do
14
- index_scope City
15
- end
16
-
17
- stub_index(:countries) do
18
- index_scope Country
19
- end
20
- end
21
-
22
- let!(:cities) { Array.new(2) { |i| City.create! id: i + 1 } }
23
- let!(:countries) { Array.new(2) { |i| Country.create! id: i + 1 } }
24
-
25
- specify do
26
- expect { CitiesIndex.import }.to update_index(CitiesIndex).and_reindex(cities)
27
- expect { CountriesIndex.import }.to update_index(CountriesIndex).and_reindex(countries)
28
- end
29
-
30
- specify do
31
- expect { CitiesIndex.import cities.first }.to update_index(CitiesIndex).and_reindex(cities.first).only
32
- expect { CountriesIndex.import countries.last }.to update_index(CountriesIndex).and_reindex(countries.last).only
33
- end
34
-
35
- specify do
36
- expect(CitiesIndex.client).to receive(:bulk).with(hash_including(refresh: false)).once
37
- CitiesIndex.import cities.first, refresh: false
38
- end
39
- end
40
-
41
- describe '.client' do
42
- specify { expect(stub_index(:dummies1).client).to eq(stub_index(:dummies2).client) }
43
-
44
- context do
45
- before do
46
- stub_index(:dummies1)
47
- stub_index(:dummies2, Dummies1Index)
48
- end
49
-
50
- specify { expect(Dummies1Index.client).to eq(Dummies2Index.client) }
51
- end
52
- end
53
-
54
- describe '.index_name' do
55
- specify { expect { Class.new(Chewy::Index).index_name }.to raise_error Chewy::UndefinedIndex }
56
- specify { expect(Class.new(Chewy::Index) { index_name :myindex }.index_name).to eq('myindex') }
57
- specify { expect(stub_const('DeveloperIndex', Class.new(Chewy::Index)).index_name).to eq('developer') }
58
- specify { expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name).to eq('developers') }
59
-
60
- specify do
61
- expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name(suffix: '')).to eq('developers')
62
- end
63
- specify do
64
- expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name(suffix: '2013')).to eq('developers_2013')
65
- end
66
- specify do
67
- expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name(prefix: '')).to eq('developers')
68
- end
69
- specify do
70
- expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name(prefix: 'test')).to eq('test_developers')
71
- end
72
-
73
- context do
74
- before { allow(Chewy).to receive_messages(configuration: {prefix: 'testing'}) }
75
- specify { expect(DummiesIndex.index_name).to eq('testing_dummies') }
76
- specify { expect(stub_index(:dummies) { index_name :users }.index_name).to eq('testing_users') }
77
- specify { expect(stub_index(:dummies) { index_name :users }.index_name(prefix: '')).to eq('users') }
78
- end
79
- end
80
-
81
- describe '.derivable_name' do
82
- specify { expect(Class.new(Chewy::Index).derivable_name).to be_nil }
83
- specify { expect(stub_index(:places).derivable_name).to eq('places') }
84
- specify { expect(stub_index('namespace/places').derivable_name).to eq('namespace/places') }
85
- end
86
-
87
- describe '.prefix' do
88
- before { allow(Chewy).to receive_messages(configuration: {prefix: 'testing'}) }
89
- specify { expect(Class.new(Chewy::Index).prefix).to eq('testing') }
90
- end
91
-
92
- describe '.index_scope' do
93
- specify { expect(DummiesIndex.adapter.name).to eq('Default') }
94
-
95
- context do
96
- before { stub_index(:dummies) { index_scope :dummy, name: :borogoves } }
97
- specify { expect(DummiesIndex.adapter.name).to eq('Borogoves') }
98
- end
99
-
100
- context do
101
- before { stub_class(:city) }
102
- before { stub_index(:dummies) { index_scope City, name: :country } }
103
- specify { expect(DummiesIndex.adapter.name).to eq('Country') }
104
- end
105
-
106
- context do
107
- before { stub_class('City') }
108
- before { stub_class('Country') }
109
-
110
- specify do
111
- expect do
112
- Kernel.eval <<-DUMMY_CITY_INDEX
113
- class DummyCityIndex2 < Chewy::Index
114
- index_scope City
115
- index_scope Country
116
- end
117
- DUMMY_CITY_INDEX
118
- end.to raise_error(/Index scope is already defined/)
119
-
120
- expect do
121
- Kernel.eval <<-DUMMY_CITY_INDEX
122
- class DummyCityIndex2 < Chewy::Index
123
- index_scope City::Nothing
124
- end
125
- DUMMY_CITY_INDEX
126
- end.to raise_error(NameError)
127
- end
128
- end
129
- end
130
-
131
- describe '.settings' do
132
- before do
133
- allow(Chewy).to receive_messages(config: Chewy::Config.send(:new))
134
-
135
- Chewy.analyzer :name, filter: %w[lowercase icu_folding names_nysiis]
136
- Chewy.analyzer :phone, tokenizer: 'ngram', char_filter: ['phone']
137
- Chewy.tokenizer :ngram, type: 'nGram', min_gram: 3, max_gram: 3
138
- Chewy.char_filter :phone, type: 'pattern_replace', pattern: '[^\d]', replacement: ''
139
- Chewy.filter :names_nysiis, type: 'phonetic', encoder: 'nysiis', replace: false
140
- end
141
-
142
- let(:documents) do
143
- stub_index(:documents) do
144
- settings analysis: {analyzer: [:name, :phone, {sorted: {option: :baz}}]}
145
- end
146
- end
147
-
148
- specify { expect { documents.settings_hash }.to_not change(documents._settings, :inspect) }
149
- specify do
150
- expect(documents.settings_hash).to eq(settings: {analysis: {
151
- analyzer: {name: {filter: %w[lowercase icu_folding names_nysiis]},
152
- phone: {tokenizer: 'ngram', char_filter: ['phone']},
153
- sorted: {option: :baz}},
154
- tokenizer: {ngram: {type: 'nGram', min_gram: 3, max_gram: 3}},
155
- char_filter: {phone: {type: 'pattern_replace', pattern: '[^\d]', replacement: ''}},
156
- filter: {names_nysiis: {type: 'phonetic', encoder: 'nysiis', replace: false}}
157
- }})
158
- end
159
- end
160
-
161
- describe '.scopes' do
162
- before do
163
- stub_index(:places) do
164
- def self.by_rating; end
165
-
166
- def self.colors(*colors)
167
- filter(terms: {colors: colors.flatten(1).map(&:to_s)})
168
- end
169
-
170
- def self.by_id; end
171
- field :colors
172
- end
173
- end
174
-
175
- specify { expect(described_class.scopes).to eq([]) }
176
- specify { expect(PlacesIndex.scopes).to match_array(%i[by_rating colors by_id]) }
177
-
178
- context do
179
- before do
180
- drop_indices
181
- PlacesIndex.import!(
182
- double(colors: ['red']),
183
- double(colors: %w[red green]),
184
- double(colors: %w[green yellow])
185
- )
186
- end
187
-
188
- specify do
189
- expect(PlacesIndex.colors(:green).map(&:colors))
190
- .to contain_exactly(%w[red green], %w[green yellow])
191
- end
192
-
193
- specify do
194
- expect(PlacesIndex.colors(:green).map(&:colors))
195
- .to contain_exactly(%w[red green], %w[green yellow])
196
- end
197
- end
198
- end
199
-
200
- describe '.settings_hash' do
201
- before { allow(Chewy).to receive_messages(config: Chewy::Config.send(:new)) }
202
-
203
- specify { expect(stub_index(:documents).settings_hash).to eq({}) }
204
- specify do
205
- expect(stub_index(:documents) do
206
- settings number_of_shards: 1
207
- end.settings_hash).to eq(settings: {number_of_shards: 1})
208
- end
209
- end
210
-
211
- describe '.mappings_hash' do
212
- specify { expect(stub_index(:documents).mappings_hash).to eq({}) }
213
- specify { expect(stub_index(:documents) { index_scope :document }.mappings_hash).to eq({}) }
214
- specify do
215
- expect(stub_index(:documents) do
216
- field :date, type: 'date'
217
- end.mappings_hash).to eq(mappings: {properties: {date: {type: 'date'}}})
218
- end
219
- end
220
-
221
- describe '.specification_hash' do
222
- before { allow(Chewy).to receive_messages(config: Chewy::Config.send(:new)) }
223
-
224
- specify { expect(stub_index(:documents).specification_hash).to eq({}) }
225
- specify do
226
- expect(stub_index(:documents) do
227
- settings number_of_shards: 1
228
- end.specification_hash.keys).to eq([:settings])
229
- end
230
- specify do
231
- expect(stub_index(:documents) do
232
- field :name
233
- end.specification_hash.keys).to eq([:mappings])
234
- end
235
- specify do
236
- expect(stub_index(:documents) do
237
- settings number_of_shards: 1
238
- field :name
239
- end.specification_hash.keys).to match_array(%i[mappings settings])
240
- end
241
- end
242
-
243
- describe '.specification' do
244
- subject { stub_index(:documents) }
245
- specify { expect(subject.specification).to be_a(Chewy::Index::Specification) }
246
- specify { expect(subject.specification).to equal(subject.specification) }
247
- end
248
-
249
- context 'index call inside index', :orm do
250
- before do
251
- stub_index(:cities) do
252
- field :country_name, value: (lambda do |city|
253
- CountriesIndex.filter(term: {_id: city.country_id}).first.name
254
- end)
255
- end
256
-
257
- stub_index(:countries) do
258
- field :name
259
- end
260
-
261
- CountriesIndex.import!(double(id: 1, name: 'Country'))
262
- end
263
-
264
- specify do
265
- expect { CitiesIndex.import!(double(country_id: 1)) }
266
- .to update_index(CitiesIndex).and_reindex(country_name: 'Country')
267
- end
268
- end
269
- end
@@ -1,223 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Chewy::Journal do
4
- context 'journaling', :orm do
5
- ['', 'namespace/'].each do |namespace|
6
- context namespace.present? ? 'with namespace' : 'without namespace' do
7
- before do
8
- stub_model(:city) do
9
- update_index "#{namespace}cities", :self
10
- end
11
- stub_model(:country) do
12
- update_index "#{namespace}countries", :self
13
- end
14
-
15
- stub_index("#{namespace}cities") do
16
- index_scope City
17
- default_import_options journal: true
18
- end
19
- stub_index("#{namespace}countries") do
20
- index_scope Country
21
- default_import_options journal: true
22
- end
23
-
24
- drop_indices
25
- Chewy.settings[:prefix] = 'some_prefix'
26
- Timecop.freeze(time)
27
- end
28
-
29
- after do
30
- Chewy.settings[:prefix] = nil
31
- Timecop.return
32
- end
33
-
34
- let(:time) { Time.now }
35
- let(:import_time) { time + 1 }
36
- let(:update_time) { time + 2 }
37
- let(:destroy_time) { time + 3 }
38
-
39
- def timestamp(time)
40
- time.to_i
41
- end
42
-
43
- specify do
44
- cities_index = namespace.present? ? Namespace::CitiesIndex : CitiesIndex
45
- countries_index = namespace.present? ? Namespace::CountriesIndex : CountriesIndex
46
- Chewy.strategy(:urgent) do
47
- cities = Array.new(2) { |i| City.create!(id: i + 1) }
48
- countries = Array.new(2) { |i| Country.create!(id: i + 1) }
49
- Country.create!(id: 3)
50
-
51
- Timecop.freeze(import_time)
52
-
53
- cities_index.import
54
- countries_index.import
55
-
56
- expect(Chewy::Stash::Journal.exists?).to eq true
57
-
58
- Timecop.freeze(update_time)
59
- cities.first.update!(name: 'Supername')
60
-
61
- Timecop.freeze(destroy_time)
62
- countries.last.destroy
63
-
64
- journal_entries = Chewy::Stash::Journal.order(:created_at).hits.map { |r| r['_source'] }
65
- expected_journal = [
66
- {
67
- 'index_name' => "#{namespace}cities",
68
- 'action' => 'index',
69
- 'references' => ['1'].map(&Base64.method(:encode64)),
70
- 'created_at' => time.utc.as_json
71
- },
72
- {
73
- 'index_name' => "#{namespace}cities",
74
- 'action' => 'index',
75
- 'references' => ['2'].map(&Base64.method(:encode64)),
76
- 'created_at' => time.utc.as_json
77
- },
78
- {
79
- 'index_name' => "#{namespace}countries",
80
- 'action' => 'index',
81
- 'references' => ['1'].map(&Base64.method(:encode64)),
82
- 'created_at' => time.utc.as_json
83
- },
84
- {
85
- 'index_name' => "#{namespace}countries",
86
- 'action' => 'index',
87
- 'references' => ['2'].map(&Base64.method(:encode64)),
88
- 'created_at' => time.utc.as_json
89
- },
90
- {
91
- 'index_name' => "#{namespace}countries",
92
- 'action' => 'index',
93
- 'references' => ['3'].map(&Base64.method(:encode64)),
94
- 'created_at' => time.utc.as_json
95
- },
96
- {
97
- 'index_name' => "#{namespace}cities",
98
- 'action' => 'index',
99
- 'references' => %w[1 2].map(&Base64.method(:encode64)),
100
- 'created_at' => import_time.utc.as_json
101
- },
102
- {
103
- 'index_name' => "#{namespace}countries",
104
- 'action' => 'index',
105
- 'references' => %w[1 2 3].map(&Base64.method(:encode64)),
106
- 'created_at' => import_time.utc.as_json
107
- },
108
- {
109
- 'index_name' => "#{namespace}cities",
110
- 'action' => 'index',
111
- 'references' => ['1'].map(&Base64.method(:encode64)),
112
- 'created_at' => update_time.utc.as_json
113
- },
114
- {
115
- 'index_name' => "#{namespace}countries",
116
- 'action' => 'delete',
117
- 'references' => ['2'].map(&Base64.method(:encode64)),
118
- 'created_at' => destroy_time.utc.as_json
119
- }
120
- ]
121
-
122
- expect(Chewy::Stash::Journal.count).to eq 9
123
- expect(journal_entries).to eq expected_journal
124
-
125
- journal_entries = Chewy::Stash::Journal.entries(import_time - 1)
126
- expect(journal_entries.size).to eq 4
127
-
128
- # simulate lost data
129
- Chewy.client.delete(index: "#{Chewy.settings[:prefix]}_cities", id: 1, refresh: true)
130
- expect(cities_index.count).to eq 1
131
-
132
- described_class.new.apply(time)
133
- expect(cities_index.count).to eq 2
134
-
135
- clean_response = described_class.new.clean(import_time)
136
- expect(clean_response['deleted'] || clean_response['_indices']['_all']['deleted']).to eq 7
137
- Chewy.client.indices.refresh
138
- expect(Chewy::Stash::Journal.count).to eq 2
139
-
140
- Timecop.return
141
- end
142
- end
143
- end
144
- end
145
- end
146
-
147
- context do
148
- before { drop_indices }
149
- before do
150
- stub_model(:city) do
151
- update_index 'cities', :self
152
- end
153
- stub_model(:country) do
154
- update_index 'countries', :self
155
- end
156
-
157
- stub_index(:cities) do
158
- index_scope City
159
- default_import_options journal: true
160
- end
161
- stub_index(:countries) do
162
- index_scope Country
163
- default_import_options journal: true
164
- end
165
- end
166
-
167
- describe '#apply' do
168
- specify { expect(described_class.new(CitiesIndex).apply(2.minutes.ago)).to eq(0) }
169
-
170
- context 'with an index filter' do
171
- let(:time) { Time.now }
172
-
173
- before { Timecop.freeze(time) }
174
- after { Timecop.return }
175
-
176
- specify do
177
- Chewy.strategy(:urgent) do
178
- Array.new(2) { |i| City.create!(id: i + 1) }
179
- Array.new(2) { |i| Country.create!(id: i + 1) }
180
-
181
- # simulate lost data
182
- Chewy.client.delete(index: 'cities', id: 1, refresh: true)
183
- Chewy.client.delete(index: 'countries', id: 1, refresh: true)
184
- expect(CitiesIndex.all.to_a.length).to eq 1
185
- expect(CountriesIndex.all.to_a.length).to eq 1
186
-
187
- # Replay on specific index
188
- expect(described_class.new(CitiesIndex).apply(time)).to eq(2)
189
- expect(CitiesIndex.all.to_a.length).to eq 2
190
- expect(CountriesIndex.all.to_a.length).to eq 1
191
-
192
- # Replay on both
193
- Chewy.client.delete(index: 'cities', id: 1, refresh: true)
194
- expect(CitiesIndex.all.to_a.length).to eq 1
195
- expect(described_class.new(CitiesIndex, CountriesIndex).apply(time)).to eq(4)
196
- expect(CitiesIndex.all.to_a.length).to eq 2
197
- expect(CountriesIndex.all.to_a.length).to eq 2
198
- end
199
- end
200
- end
201
-
202
- context 'when order is not preserved' do
203
- let(:time) { Time.now }
204
-
205
- it 'paginates properly through all items' do
206
- Chewy.strategy(:urgent) do
207
- Timecop.travel(time + 1.minute) { City.create!(id: 2) }
208
- Timecop.travel(time + 3.minute) { City.create!(id: 4) }
209
- Timecop.travel(time + 2.minute) { City.create!(id: 1) }
210
- Timecop.travel(time + 4.minute) { City.create!(id: 3) }
211
- end
212
-
213
- CitiesIndex.purge!
214
- expect(CitiesIndex.all.to_a.length).to eq 0
215
-
216
- # Replay on specific index
217
- expect(described_class.new(CitiesIndex).apply(time, fetch_limit: 2)).to eq(4)
218
- expect(CitiesIndex.all.to_a.map(&:id).sort).to eq([1, 2, 3, 4])
219
- end
220
- end
221
- end
222
- end
223
- end
@@ -1,194 +0,0 @@
1
- require 'spec_helper'
2
- require 'chewy/minitest'
3
-
4
- describe :minitest_helper do
5
- class << self
6
- alias_method :teardown, :after
7
- end
8
-
9
- def assert_includes(haystack, needle, _comment)
10
- expect(haystack).to include(needle)
11
- end
12
-
13
- include Chewy::Minitest::Helpers
14
-
15
- def assert_equal(expected, actual, message)
16
- raise message unless expected == actual
17
- end
18
-
19
- before do
20
- drop_indices
21
- end
22
-
23
- before do
24
- stub_index(:dummies) do
25
- root value: ->(_o) { {} }
26
- end
27
- end
28
-
29
- describe 'mock_elasticsearch_response' do
30
- let(:hits) do
31
- [
32
- {
33
- '_index' => 'dummies',
34
- '_type' => '_doc',
35
- '_id' => '2',
36
- '_score' => 3.14,
37
- '_source' => source
38
- }
39
- ]
40
- end
41
-
42
- let(:source) { {'name' => 'some_name', id: '2'} }
43
- let(:sources) { [source] }
44
-
45
- context 'mocks by raw response' do
46
- let(:raw_response) do
47
- {
48
- 'took' => 4,
49
- 'timed_out' => false,
50
- '_shards' => {
51
- 'total' => 1,
52
- 'successful' => 1,
53
- 'skipped' => 0,
54
- 'failed' => 0
55
- },
56
- 'hits' => {
57
- 'total' => {
58
- 'value' => 1,
59
- 'relation' => 'eq'
60
- },
61
- 'max_score' => 1.0,
62
- 'hits' => hits
63
- }
64
- }
65
- end
66
-
67
- specify do
68
- mock_elasticsearch_response(DummiesIndex, raw_response) do
69
- expect(DummiesIndex.query({}).hits).to eq(hits)
70
- end
71
- end
72
- end
73
-
74
- context 'mocks by response sources' do
75
- specify do
76
- mock_elasticsearch_response_sources(DummiesIndex, sources) do
77
- expect(DummiesIndex.query({}).hits).to eq(hits)
78
- end
79
- end
80
- end
81
- end
82
-
83
- describe 'assert correct elasticsearch query' do
84
- let(:query) do
85
- DummiesIndex.filter.should { multi_match foo: 'bar' }.filter { match foo: 'bar' }
86
- end
87
-
88
- let(:expected_query) do
89
- {
90
- index: ['dummies'],
91
- body: {
92
- query: {
93
- bool: {
94
- filter: {
95
- bool: {
96
- must: {
97
- match: {foo: 'bar'}
98
- },
99
- should: {
100
- multi_match: {foo: 'bar'}
101
- }
102
- }
103
- }
104
- }
105
- }
106
- }
107
- }
108
- end
109
-
110
- context 'will be built' do
111
- specify do
112
- expect { assert_elasticsearch_query(query, expected_query) }.not_to raise_error
113
- end
114
- end
115
-
116
- context 'will not be built' do
117
- let(:unexpected_query) do
118
- {
119
- index: ['what?'],
120
- body: {}
121
- }
122
- end
123
-
124
- specify do
125
- expect { assert_elasticsearch_query(query, unexpected_query) }
126
- .to raise_error(RuntimeError, /instead of expected query\./)
127
- end
128
- end
129
- end
130
-
131
- context 'assert_indexes' do
132
- specify 'doesn\'t fail when index updates correctly' do
133
- expect do
134
- assert_indexes DummiesIndex do
135
- DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}]
136
- end
137
- end.to_not raise_error
138
- end
139
-
140
- specify 'fails when index doesn\'t update' do
141
- expect do
142
- assert_indexes DummiesIndex do
143
- end
144
- end.to raise_error(RSpec::Expectations::ExpectationNotMetError)
145
- end
146
-
147
- specify 'SearchIndexReceiver catches the indexes' do
148
- receiver = assert_indexes DummiesIndex do
149
- DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}]
150
- end
151
-
152
- expect(receiver).to be_a(SearchIndexReceiver)
153
-
154
- expect(
155
- receiver.indexes_for(DummiesIndex)
156
- .map { |index| index[:_id] }
157
- ).to match_array([41, 42])
158
- end
159
-
160
- specify 'Real index is bypassed when asserting' do
161
- expect(DummiesIndex).not_to receive(:bulk)
162
-
163
- assert_indexes DummiesIndex do
164
- DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}]
165
- end
166
- end
167
-
168
- specify 'Real index is allowed when asserting' do
169
- expect(DummiesIndex).to receive(:bulk)
170
-
171
- assert_indexes DummiesIndex, bypass_actual_index: false do
172
- DummiesIndex.bulk body: [{index: {_id: 42, data: {}}}, {index: {_id: 41, data: {}}}]
173
- end
174
- end
175
- end
176
-
177
- context 'run_indexing' do
178
- specify 'pushes onto the chewy strategy stack' do
179
- Chewy.strategy :bypass do
180
- run_indexing do
181
- expect(Chewy.strategy.current.name).to be(:atomic)
182
- end
183
- end
184
- end
185
-
186
- specify 'allows tester to specify the strategy' do
187
- Chewy.strategy :atomic do
188
- run_indexing strategy: :bypass do
189
- expect(Chewy.strategy.current.name).to be(:bypass)
190
- end
191
- end
192
- end
193
- end
194
- end