chewy 7.2.1 → 7.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70c6d061a7070669eafe4f28bd09cd8e7a9138d0a66dd6fdbdf1f387f3f3f0af
4
- data.tar.gz: '03838f9c5e5b323e68482066b057bccff969e2826e581b994b92a962bb45e272'
3
+ metadata.gz: 229c412b1e3464060b367c9c378d3662bccf2329b4e4eaa7617541243dbd6e38
4
+ data.tar.gz: 9bc674550cd6152e8a18853fa46c91873c7a626c426cd50aa2cb8c67b1c9455e
5
5
  SHA512:
6
- metadata.gz: 8fcafb7b237abf426ed941e6b8d53b537db65186ce98f40b6c1b50257bc570b500b9bbff71aedb6828dfb0be11e13f031f3cf92413fd0f3efb5b860deca53a28
7
- data.tar.gz: c74fe5e6db07346b9e77f4a0d294317a6ade800fa506f231d7368058a6f058785bb0c9756110378b810398a7bc24ca5c695bbb46c330a97976fd3b1bf6a8d3da
6
+ metadata.gz: e3e8409f81bc2504e9edbf5093fc9329bf443862cb96e113c9c00fc586c1e0e3a4273b3d6e82466f9b3d301e3d9eafcc72892cce718aff7dcfbbce85aba1698d
7
+ data.tar.gz: 33b5b0e21ef7c9896f1ed381130f225a1d51e073112213f631fb1c57c6d69c49af54817b1de3afc9be325c79ac24f9c173275b4448ffb7b43e82403bee03bd70
data/CHANGELOG.md CHANGED
@@ -8,6 +8,25 @@
8
8
 
9
9
  ### Bugs Fixed
10
10
 
11
+ ## 7.2.2 (2021-05-24)
12
+
13
+ ### Changes
14
+
15
+ * [#800](https://github.com/toptal/chewy/pull/800): Revert [#787](https://github.com/toptal/chewy/pull/787) progressbar feature to avoid performance degradation in parallel import ([@rabotyaga][])
16
+
17
+ * [#795](https://github.com/toptal/chewy/issues/795): **(Breaking)** Change the Chewy::Search::Parameters::Order implementation to use Array ([@jiajiawang][]):
18
+ * To allow multiple sorting options that may have the same key name. For example script based sorting whose key will always be `_script`.
19
+ * Behaviour change of chained `order` calls.
20
+ * e.g. `.order(_script: {a: 1}).order(_script: {b: 2})`
21
+ * Before `{:sort=>[{"_script"=>{:b=>2}}]}`
22
+ * After `{:sort=>[{"_script"=>{:a=>1}},{"_script"=>{:b=>2}}]}`
23
+
24
+ * [#654](https://github.com/toptal/chewy/issues/654): Add helpers and matchers for testing ([@Vitalina-Vakulchyk][]):
25
+ * `mock_elasticsearch_response` helpers both Rspec and Minitest - to mock elasticsearch response
26
+ * `mock_elasticsearch_response_sources` helpers both Rspec and Minitest - to mock elasticsearch response sources
27
+ * `assert_elasticsearch_query` helper for Minitest - to compare request and expected query (returns `true`/`false`)
28
+ * `build_query` matcher for Rspec - to compare request and expected query (returns `true`/`false`)
29
+
11
30
  ## 7.2.1 (2021-05-11)
12
31
 
13
32
  ### New Features
@@ -631,6 +650,7 @@
631
650
  [@inbeom]: https://github.com/inbeom
632
651
  [@jesjos]: https://github.com/jesjos
633
652
  [@JF-Lalonde]: https://github.com/JF-Lalonde
653
+ [@jiajiawang]: https://github.com/jiajiawang
634
654
  [@jimmybaker]: https://github.com/jimmybaker
635
655
  [@jirikolarik]: https://github.com/jirikolarik
636
656
  [@jirutka]: https://github.com/jirutka
data/README.md CHANGED
@@ -53,7 +53,7 @@ Chewy is compatible with MRI 2.6-3.0¹.
53
53
  | ------------- | ---------------------------------- |
54
54
  | 7.2.x | 7.x |
55
55
  | 7.1.x | 7.x |
56
- | 7.0.0 | 6.8, 7.x |
56
+ | 7.0.x | 6.8, 7.x |
57
57
  | 6.0.0 | 5.x, 6.x |
58
58
  | 5.x | 5.x, limited support for 1.x & 2.x |
59
59
 
@@ -1032,12 +1032,6 @@ rake chewy:reset[users,cities] # resets UsersIndex and CitiesIndex
1032
1032
  rake chewy:reset[-users,cities] # resets every index in the application except specified ones
1033
1033
  ```
1034
1034
 
1035
- #### Progressbar for `chewy:reset` tasks
1036
-
1037
- You can optionally output the `progressbar` for `chewy:reset` and `chewy:parallel:reset` during import.
1038
-
1039
- Progressbar is hidden by default. Set `ENV['PROGRESS']` to `true` to display it.
1040
-
1041
1035
  #### `chewy:upgrade`
1042
1036
 
1043
1037
  Performs reset exactly the same way as `chewy:reset` does, but only when the index specification (setting or mapping) was changed.
@@ -1117,7 +1111,16 @@ rake chewy:journal:apply["$(date -v-1H -u +%FT%TZ)",users] # apply journaled cha
1117
1111
 
1118
1112
  ### RSpec integration
1119
1113
 
1120
- Just add `require 'chewy/rspec'` to your spec_helper.rb and you will get additional features: See [update_index.rb](lib/chewy/rspec/update_index.rb) for more details.
1114
+ Just add `require 'chewy/rspec'` to your spec_helper.rb and you will get additional features:
1115
+
1116
+ [update_index](lib/chewy/rspec/update_index.rb) helper
1117
+ `mock_elasticsearch_response` helper to mock elasticsearch response
1118
+ `mock_elasticsearch_response_sources` helper to mock elasticsearch response sources
1119
+ `build_query` matcher to compare request and expected query (returns `true`/`false`)
1120
+
1121
+ To use `mock_elasticsearch_response` and `mock_elasticsearch_response_sources` helpers add `include Chewy::Rspec::Helpers` to your tests.
1122
+
1123
+ See [chewy/rspec/](lib/chewy/rspec/) for more details.
1121
1124
 
1122
1125
  ### Minitest integration
1123
1126
 
@@ -1127,6 +1130,14 @@ Since you can set `:bypass` strategy for test suites and manually handle import
1127
1130
 
1128
1131
  But if you require chewy to index/update model regularly in your test suite then you can specify `:urgent` strategy for documents indexing. Add `Chewy.strategy(:urgent)` to test_helper.rb.
1129
1132
 
1133
+ Also, you can use additional helpers:
1134
+
1135
+ `mock_elasticsearch_response` to mock elasticsearch response
1136
+ `mock_elasticsearch_response_sources` to mock elasticsearch response sources
1137
+ `assert_elasticsearch_query` to compare request and expected query (returns `true`/`false`)
1138
+
1139
+ See [chewy/minitest/](lib/chewy/minitest/) for more details.
1140
+
1130
1141
  ### DatabaseCleaner
1131
1142
 
1132
1143
  If you use `DatabaseCleaner` in your tests with [the `transaction` strategy](https://github.com/DatabaseCleaner/database_cleaner#how-to-use), you may run into the problem that `ActiveRecord`'s models are not indexed automatically on save despite the fact that you set the callbacks to do this with the `update_index` method. The issue arises because `chewy` indices data on `after_commit` run as default, but all `after_commit` callbacks are not run with the `DatabaseCleaner`'s' `transaction` strategy. You can solve this issue by changing the `Chewy.use_after_commit_callbacks` option. Just add the following initializer in your Rails application:
data/chewy.gemspec CHANGED
@@ -31,7 +31,6 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
31
31
  spec.add_development_dependency 'unparser'
32
32
 
33
33
  spec.add_dependency 'activesupport', '>= 5.2'
34
- spec.add_dependency 'elasticsearch', '>= 6.3.0'
34
+ spec.add_dependency 'elasticsearch', '>= 7.12.0'
35
35
  spec.add_dependency 'elasticsearch-dsl'
36
- spec.add_dependency 'ruby-progressbar'
37
36
  end
@@ -146,7 +146,7 @@ module Chewy
146
146
  # @param journal [true, false] journaling is switched off for import during reset by default
147
147
  # @param import_options [Hash] options, passed to the import call
148
148
  # @return [true, false] false in case of errors
149
- def reset!(suffix = nil, apply_journal: true, journal: false, progressbar: false, **import_options)
149
+ def reset!(suffix = nil, apply_journal: true, journal: false, **import_options)
150
150
  result = if suffix.present?
151
151
  start_time = Time.now
152
152
  indexes = self.indexes - [index_name]
@@ -159,13 +159,17 @@ module Chewy
159
159
  result = import import_options.merge(
160
160
  suffix: suffix,
161
161
  journal: journal,
162
- refresh: !Chewy.reset_disable_refresh_interval,
163
- progressbar: progressbar
162
+ refresh: !Chewy.reset_disable_refresh_interval
164
163
  )
165
164
  original_index_settings suffixed_name
166
165
 
167
166
  delete if indexes.blank?
168
- update_aliases(indexes, general_name, suffixed_name)
167
+ client.indices.update_aliases body: {actions: [
168
+ *indexes.map do |index|
169
+ {remove: {index: index, alias: general_name}}
170
+ end,
171
+ {add: {index: suffixed_name, alias: general_name}}
172
+ ]}
169
173
  client.indices.delete index: indexes if indexes.present?
170
174
 
171
175
  self.journal.apply(start_time, **import_options) if apply_journal
@@ -233,15 +237,6 @@ module Chewy
233
237
 
234
238
  private
235
239
 
236
- def update_aliases(indexes, general_name, suffixed_name)
237
- client.indices.update_aliases body: {actions: [
238
- *indexes.map do |index|
239
- {remove: {index: index, alias: general_name}}
240
- end,
241
- {add: {index: suffixed_name, alias: general_name}}
242
- ]}
243
- end
244
-
245
240
  def optimize_index_settings(index_name)
246
241
  settings = {}
247
242
  settings[:refresh_interval] = -1 if Chewy.reset_disable_refresh_interval
@@ -192,16 +192,6 @@ module Chewy
192
192
  end
193
193
  end
194
194
 
195
- def import_count(*args)
196
- collection = if args.first.empty? && @target.respond_to?(import_all_method)
197
- @target.send(import_all_method)
198
- else
199
- args.flatten(1).compact
200
- end
201
-
202
- collection.count
203
- end
204
-
205
195
  private
206
196
 
207
197
  def import_objects(objects, options)
@@ -108,18 +108,6 @@ module Chewy
108
108
  ids.map { |id| loaded_objects[id.to_s] }
109
109
  end
110
110
 
111
- def import_count(*args)
112
- collection = if args.first.empty?
113
- default_scope
114
- elsif args.first.is_a?(relation_class)
115
- args.first
116
- else
117
- args.flatten.compact
118
- end
119
-
120
- collection.count
121
- end
122
-
123
111
  private
124
112
 
125
113
  def import_objects(collection, options)
@@ -2,19 +2,17 @@ require 'chewy/index/import/journal_builder'
2
2
  require 'chewy/index/import/bulk_builder'
3
3
  require 'chewy/index/import/bulk_request'
4
4
  require 'chewy/index/import/routine'
5
- require 'chewy/index/import/thread_safe_progress_bar'
6
5
 
7
6
  module Chewy
8
7
  class Index
9
8
  module Import
10
9
  extend ActiveSupport::Concern
11
10
 
12
- IMPORT_WORKER = lambda do |index, options, total, progress_bar, ids, iteration|
11
+ IMPORT_WORKER = lambda do |index, options, total, ids, iteration|
13
12
  ::Process.setproctitle("chewy [#{index}]: import data (#{iteration + 1}/#{total})")
14
13
  routine = Routine.new(index, **options)
15
14
  index.adapter.import(*ids, routine.options) do |action_objects|
16
15
  routine.process(**action_objects)
17
- progress_bar.increment(action_objects.map { |_, v| v.size }.sum) if routine.options[:progressbar]
18
16
  end
19
17
  {errors: routine.errors, import: routine.stats, leftovers: routine.leftovers}
20
18
  end
@@ -152,10 +150,8 @@ module Chewy
152
150
 
153
151
  def import_linear(objects, routine)
154
152
  ActiveSupport::Notifications.instrument 'import_objects.chewy', index: self do |payload|
155
- progress_bar = ThreadSafeProgressBar.new(routine.options[:progressbar]) { adapter.import_count(objects) }
156
153
  adapter.import(*objects, routine.options) do |action_objects|
157
154
  routine.process(**action_objects)
158
- progress_bar.increment(action_objects.map { |_, v| v.size }.sum) if routine.options[:progressbar]
159
155
  end
160
156
  routine.perform_bulk(routine.leftovers)
161
157
  payload[:import] = routine.stats
@@ -170,20 +166,24 @@ module Chewy
170
166
  ActiveSupport::Notifications.instrument 'import_objects.chewy', index: self do |payload|
171
167
  batches = adapter.import_references(*objects, routine.options.slice(:batch_size)).to_a
172
168
 
173
- progress_bar = ThreadSafeProgressBar.new(routine.options[:progressbar]) { adapter.import_count(objects) }
174
169
  ::ActiveRecord::Base.connection.close if defined?(::ActiveRecord::Base)
175
-
176
- results = ::Parallel.map_with_index(batches, routine.parallel_options) do |ids, index|
177
- progress_bar.wait_until_ready
178
- ActiveRecord::Base.connection_pool.with_connection do
179
- IMPORT_WORKER.call(self, routine.options, total, progress_bar, ids, index)
180
- end
181
- end
182
-
170
+ results = ::Parallel.map_with_index(
171
+ batches,
172
+ routine.parallel_options,
173
+ &IMPORT_WORKER.curry[self, routine.options, batches.size]
174
+ )
183
175
  ::ActiveRecord::Base.connection.reconnect! if defined?(::ActiveRecord::Base)
184
176
  errors, import, leftovers = process_parallel_import_results(results)
185
177
 
186
- execute_leftovers(leftovers, routine, self, errors)
178
+ if leftovers.present?
179
+ batches = leftovers.each_slice(routine.options[:batch_size])
180
+ results = ::Parallel.map_with_index(
181
+ batches,
182
+ routine.parallel_options,
183
+ &LEFTOVERS_WORKER.curry[self, routine.options, batches.size]
184
+ )
185
+ errors.concat(results.flatten(1))
186
+ end
187
187
 
188
188
  payload[:import] = import
189
189
  payload[:errors] = payload_errors(errors) if errors.present?
@@ -191,18 +191,6 @@ module Chewy
191
191
  end
192
192
  end
193
193
 
194
- def execute_leftovers(leftovers, routine, self_object, errors)
195
- return unless leftovers.present?
196
-
197
- batches = leftovers.each_slice(routine.options[:batch_size])
198
- results = ::Parallel.map_with_index(
199
- batches,
200
- routine.parallel_options,
201
- &LEFTOVERS_WORKER.curry[self_object, routine.options, batches.size]
202
- )
203
- errors.concat(results.flatten(1))
204
- end
205
-
206
194
  def process_parallel_import_results(results)
207
195
  results.each_with_object([[], {}, []]) do |r, (e, i, l)|
208
196
  e.concat(r[:errors])
@@ -51,9 +51,9 @@ module Chewy
51
51
  @parallel_options = @options.delete(:parallel)
52
52
  if @parallel_options && !@parallel_options.is_a?(Hash)
53
53
  @parallel_options = if @parallel_options.is_a?(Integer)
54
- {in_threads: @parallel_options}
54
+ {in_processes: @parallel_options}
55
55
  else
56
- {in_threads: [::Parallel.processor_count, ActiveRecord::Base.connection_pool.size].min}
56
+ {}
57
57
  end
58
58
  end
59
59
  @errors = []
@@ -42,10 +42,87 @@ module Chewy
42
42
  # Run indexing for the database changes during the block provided.
43
43
  # By default, indexing is run at the end of the block.
44
44
  # @param strategy [Symbol] the Chewy index update strategy see Chewy docs.
45
+ #
45
46
  def run_indexing(strategy: :atomic, &block)
46
47
  Chewy.strategy strategy, &block
47
48
  end
48
49
 
50
+ # Mock Elasticsearch response
51
+ # Simple usage - just pass index, expected raw response
52
+ # and block with the query.
53
+ #
54
+ # @param index [Chewy::Index] the index to watch, eg EntitiesIndex.
55
+ # @param raw_response [Hash] hash with response.
56
+ #
57
+ def mock_elasticsearch_response(index, raw_response)
58
+ mocked_request = Chewy::Search::Request.new(index)
59
+
60
+ original_new = Chewy::Search::Request.method(:new)
61
+
62
+ Chewy::Search::Request.define_singleton_method(:new) { |*_args| mocked_request }
63
+
64
+ original_perform = mocked_request.method(:perform)
65
+ mocked_request.define_singleton_method(:perform) { raw_response }
66
+
67
+ yield
68
+ ensure
69
+ mocked_request.define_singleton_method(:perform, original_perform)
70
+ Chewy::Search::Request.define_singleton_method(:new, original_new)
71
+ end
72
+
73
+ # Mock Elasticsearch response with defined sources
74
+ # Simple usage - just pass index, expected sources
75
+ # and block with the query.
76
+ #
77
+ # @param index [Chewy::Index] the index to watch, eg EntitiesIndex.
78
+ # @param hits [Hash] hash with sources.
79
+ #
80
+ def mock_elasticsearch_response_sources(index, hits, &block)
81
+ raw_response = {
82
+ 'took' => 4,
83
+ 'timed_out' => false,
84
+ '_shards' => {
85
+ 'total' => 1,
86
+ 'successful' => 1,
87
+ 'skipped' => 0,
88
+ 'failed' => 0
89
+ },
90
+ 'hits' => {
91
+ 'total' => {
92
+ 'value' => hits.count,
93
+ 'relation' => 'eq'
94
+ },
95
+ 'max_score' => 1.0,
96
+ 'hits' => hits.each_with_index.map do |hit, i|
97
+ {
98
+ '_index' => index.index_name,
99
+ '_type' => '_doc',
100
+ '_id' => (i + 1).to_s,
101
+ '_score' => 3.14,
102
+ '_source' => hit
103
+ }
104
+ end
105
+ }
106
+ }
107
+
108
+ mock_elasticsearch_response(index, raw_response, &block)
109
+ end
110
+
111
+ # Check the assertion that actual Elasticsearch query is rendered
112
+ # to the expected query
113
+ #
114
+ # @param query [::Query] the actual Elasticsearch query.
115
+ # @param expected_query [Hash] expected query.
116
+ #
117
+ # @return [Boolean]
118
+ # True - in the case when actual Elasticsearch query is rendered to the expected query.
119
+ # False - in the opposite case.
120
+ #
121
+ def assert_elasticsearch_query(query, expected_query)
122
+ actual_query = query.render
123
+ assert_equal expected_query, actual_query, "got #{actual_query.inspect} instead of expected query."
124
+ end
125
+
49
126
  module ClassMethods
50
127
  # Declare that all tests in this file require real indexing, always.
51
128
  # In my completely unscientific experiments, this roughly doubled test runtime.
@@ -271,7 +271,7 @@ module Chewy
271
271
 
272
272
  def reset_one(index, output, parallel: false)
273
273
  output.puts "Resetting #{index}"
274
- index.reset!((Time.now.to_f * 1000).round, parallel: parallel, progressbar: ENV['PROGRESS'] == 'true')
274
+ index.reset!((Time.now.to_f * 1000).round, parallel: parallel)
275
275
  end
276
276
  end
277
277
  end
data/lib/chewy/rspec.rb CHANGED
@@ -1 +1,3 @@
1
+ require 'chewy/rspec/build_query'
2
+ require 'chewy/rspec/helpers'
1
3
  require 'chewy/rspec/update_index'
@@ -0,0 +1,12 @@
1
+ # Rspec helper to compare request and expected query
2
+ # To use it - add `require 'chewy/rspec/build_query'` to the `spec_helper.rb`
3
+ # Simple usage - just pass expected response as argument
4
+ # and then call needed query.
5
+ #
6
+ # expect { method1.method2...methodN }.to build_query(expected_query)
7
+ #
8
+ RSpec::Matchers.define :build_query do |expected_query = {}|
9
+ match do |request|
10
+ request.render == expected_query
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ module Chewy
2
+ module Rspec
3
+ module Helpers
4
+ extend ActiveSupport::Concern
5
+ # Rspec helper to mock elasticsearch response
6
+ # To use it - add `require 'chewy/rspec'` to the `spec_helper.rb`
7
+ #
8
+ # mock_elasticsearch_response(CitiesIndex, raw_response)
9
+ # expect(CitiesIndex.query({}).hits).to eq(hits)
10
+ #
11
+ def mock_elasticsearch_response(index, raw_response)
12
+ mocked_request = Chewy::Search::Request.new(index)
13
+ allow(Chewy::Search::Request).to receive(:new).and_return(mocked_request)
14
+ allow(mocked_request).to receive(:perform).and_return(raw_response)
15
+ end
16
+
17
+ # Rspec helper to mock Elasticsearch response source
18
+ # To use it - add `require 'chewy/rspec'` to the `spec_helper.rb`
19
+ #
20
+ # mock_elasticsearch_response_sources(CitiesIndex, sources)
21
+ # expect(CitiesIndex.query({}).hits).to eq(hits)
22
+ #
23
+ def mock_elasticsearch_response_sources(index, hits)
24
+ raw_response = {
25
+ 'took' => 4,
26
+ 'timed_out' => false,
27
+ '_shards' => {
28
+ 'total' => 1,
29
+ 'successful' => 1,
30
+ 'skipped' => 0,
31
+ 'failed' => 0
32
+ },
33
+ 'hits' => {
34
+ 'total' => {
35
+ 'value' => hits.count,
36
+ 'relation' => 'eq'
37
+ },
38
+ 'max_score' => 1.0,
39
+ 'hits' => hits.each_with_index.map do |hit, i|
40
+ {
41
+ '_index' => index.index_name,
42
+ '_type' => '_doc',
43
+ '_id' => (i + 1).to_s,
44
+ '_score' => 3.14,
45
+ '_source' => hit
46
+ }
47
+ end
48
+ }
49
+ }
50
+
51
+ mock_elasticsearch_response(index, raw_response)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -17,7 +17,7 @@ module Chewy
17
17
  # @param other_value [Object] any acceptable storage value
18
18
  # @return [Object] updated value
19
19
  def update!(other_value)
20
- value.merge!(normalize(other_value))
20
+ value.concat(normalize(other_value))
21
21
  end
22
22
 
23
23
  # Size requires specialized rendering logic, it should return
@@ -28,20 +28,7 @@ module Chewy
28
28
  def render
29
29
  return if value.blank?
30
30
 
31
- sort = value.map do |(field, options)|
32
- options ? {field => options} : field
33
- end
34
- {sort: sort}
35
- end
36
-
37
- # Comparison also reqires additional logic. Hashes are compared
38
- # orderlessly, but for `sort` parameter oder is important, so we
39
- # compare hash key collections additionally.
40
- #
41
- # @see Chewy::Search::Parameters::Storage#==
42
- # @return [true, false]
43
- def ==(other)
44
- super && value.keys == other.value.keys
31
+ {sort: value}
45
32
  end
46
33
 
47
34
  private
@@ -49,13 +36,13 @@ module Chewy
49
36
  def normalize(value)
50
37
  case value
51
38
  when Array
52
- value.each_with_object({}) do |sv, res|
53
- res.merge!(normalize(sv))
39
+ value.each_with_object([]) do |sv, res|
40
+ res.concat(normalize(sv))
54
41
  end
55
42
  when Hash
56
- value.stringify_keys
43
+ [value.stringify_keys]
57
44
  else
58
- value.present? ? {value.to_s => nil} : {}
45
+ value.present? ? [value.to_s] : []
59
46
  end
60
47
  end
61
48
  end
data/lib/chewy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Chewy
2
- VERSION = '7.2.1'.freeze
2
+ VERSION = '7.2.2'.freeze
3
3
  end
data/migration_guide.md CHANGED
@@ -9,7 +9,7 @@ Chewy alongside a matching Elasticsearch version.
9
9
  In order to upgrade Chewy 6/Elasticsearch 6 to Chewy 7/Elasticsearch 7 in the most seamless manner you have to:
10
10
 
11
11
  * Upgrade to the latest 6.x stable releases, namely Chewy 6.0, Elasticsearch 6.8
12
- * Study carefully [Breaking changes in 7.0](https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.htmll), make sure your application conforms.
12
+ * Study carefully [Breaking changes in 7.0](https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html), make sure your application conforms.
13
13
  * Run your test suite on Chewy 7.0 / Elasticsearch 7
14
14
  * Run manual tests on Chewy 7.0 / Elasticsearch 7
15
15
  * Upgrade to Chewy 7.0
@@ -502,7 +502,7 @@ describe Chewy::Index::Actions do
502
502
  specify do
503
503
  expect(CitiesIndex.client.indices).to receive(:put_settings).with(index: name, body: before_import_body).once
504
504
  expect(CitiesIndex.client.indices).to receive(:put_settings).with(index: name, body: after_import_body).once
505
- expect(CitiesIndex).to receive(:import).with(suffix: suffix, progressbar: false, journal: false, refresh: false).and_call_original
505
+ expect(CitiesIndex).to receive(:import).with(suffix: suffix, journal: false, refresh: false).and_call_original
506
506
  expect(CitiesIndex.reset!(suffix)).to eq(true)
507
507
  end
508
508
 
@@ -525,7 +525,7 @@ describe Chewy::Index::Actions do
525
525
  .to receive(:put_settings).with(index: name, body: before_import_body).once
526
526
  expect(CitiesIndex.client.indices).to receive(:put_settings).with(index: name, body: after_import_body).once
527
527
  expect(CitiesIndex)
528
- .to receive(:import).with(suffix: suffix, progressbar: false, journal: false, refresh: false).and_call_original
528
+ .to receive(:import).with(suffix: suffix, journal: false, refresh: false).and_call_original
529
529
  expect(CitiesIndex.reset!(suffix)).to eq(true)
530
530
  end
531
531
 
@@ -541,7 +541,7 @@ describe Chewy::Index::Actions do
541
541
  let(:reset_disable_refresh_interval) { false }
542
542
  specify do
543
543
  expect(CitiesIndex.client.indices).not_to receive(:put_settings)
544
- expect(CitiesIndex).to receive(:import).with(suffix: suffix, progressbar: false, journal: false, refresh: true).and_call_original
544
+ expect(CitiesIndex).to receive(:import).with(suffix: suffix, journal: false, refresh: true).and_call_original
545
545
  expect(CitiesIndex.reset!(suffix)).to eq(true)
546
546
  end
547
547
  end
@@ -568,7 +568,7 @@ describe Chewy::Index::Actions do
568
568
  specify do
569
569
  expect(CitiesIndex.client.indices).to receive(:put_settings).with(index: name, body: before_import_body).once
570
570
  expect(CitiesIndex.client.indices).to receive(:put_settings).with(index: name, body: after_import_body).once
571
- expect(CitiesIndex).to receive(:import).with(suffix: suffix, progressbar: false, journal: false, refresh: true).and_call_original
571
+ expect(CitiesIndex).to receive(:import).with(suffix: suffix, journal: false, refresh: true).and_call_original
572
572
  expect(CitiesIndex.reset!(suffix)).to eq(true)
573
573
  end
574
574
  end
@@ -577,7 +577,7 @@ describe Chewy::Index::Actions do
577
577
  let(:reset_no_replicas) { false }
578
578
  specify do
579
579
  expect(CitiesIndex.client.indices).not_to receive(:put_settings)
580
- expect(CitiesIndex).to receive(:import).with(suffix: suffix, progressbar: false, journal: false, refresh: true).and_call_original
580
+ expect(CitiesIndex).to receive(:import).with(suffix: suffix, journal: false, refresh: true).and_call_original
581
581
  expect(CitiesIndex.reset!(suffix)).to eq(true)
582
582
  end
583
583
  end
@@ -667,7 +667,7 @@ describe Chewy::Index::Actions do
667
667
  specify do
668
668
  expect(CitiesIndex)
669
669
  .to receive(:import)
670
- .with(suffix: 'suffix', progressbar: false, parallel: true, journal: false, refresh: true)
670
+ .with(suffix: 'suffix', parallel: true, journal: false, refresh: true)
671
671
  .once.and_return(true)
672
672
  expect(CitiesIndex.reset!('suffix', parallel: true)).to eq(true)
673
673
  end
@@ -64,8 +64,8 @@ describe Chewy::Index::Import::Routine do
64
64
 
65
65
  describe '#parallel_options' do
66
66
  specify { expect(described_class.new(CitiesIndex).parallel_options).to be_nil }
67
- specify { expect(described_class.new(CitiesIndex, parallel: true).parallel_options).to eq({in_threads: [::Parallel.processor_count, ActiveRecord::Base.connection_pool.size].min}) }
68
- specify { expect(described_class.new(CitiesIndex, parallel: 3).parallel_options).to eq(in_threads: 3) }
67
+ specify { expect(described_class.new(CitiesIndex, parallel: true).parallel_options).to eq({}) }
68
+ specify { expect(described_class.new(CitiesIndex, parallel: 3).parallel_options).to eq(in_processes: 3) }
69
69
  specify do
70
70
  expect(described_class.new(CitiesIndex, parallel: {in_threads: 2}).parallel_options).to eq(in_threads: 2)
71
71
  end
@@ -493,35 +493,6 @@ describe Chewy::Index::Import do
493
493
 
494
494
  it_behaves_like 'importing'
495
495
  end
496
-
497
- context 'with progressbar output' do
498
- let(:mocked_progressbar) { Struct.new(:progress, :total).new(0, 100) }
499
-
500
- it 'imports tracks progress in a single batch' do
501
- expect(ProgressBar).to receive(:create).and_return(mocked_progressbar)
502
- expect(mocked_progressbar).to receive(:progress).at_least(:once).and_call_original
503
- expect(CitiesIndex).to receive(:import_parallel).and_call_original
504
-
505
- CitiesIndex.import(parallel: 1, progressbar: true)
506
-
507
- expect(mocked_progressbar.progress).to eq(3)
508
- expect(mocked_progressbar.total).to eq(3)
509
- end
510
-
511
- it 'imports tracks progress in many batches' do
512
- expect(ProgressBar).to receive(:create).and_return(mocked_progressbar)
513
- expect(mocked_progressbar).to receive(:progress).at_least(:once).and_call_original
514
- expect(CitiesIndex).to receive(:import_parallel).and_call_original
515
-
516
- batches = City.pluck(:id).map { |id| [id] }
517
- expect(CitiesIndex.adapter).to receive(:import_references).and_return(batches)
518
-
519
- CitiesIndex.import(parallel: 3, progressbar: true)
520
-
521
- expect(mocked_progressbar.progress).to eq(3)
522
- expect(mocked_progressbar.total).to eq(3)
523
- end
524
- end
525
496
  end
526
497
 
527
498
  describe '.import!', :orm do
@@ -535,9 +506,7 @@ describe Chewy::Index::Import do
535
506
  end
536
507
  end
537
508
 
538
- specify do
539
- expect { CitiesIndex.import!(dummy_cities) }.to raise_error Chewy::ImportFailed
540
- end
509
+ specify { expect { CitiesIndex.import!(dummy_cities) }.to raise_error Chewy::ImportFailed }
541
510
  end
542
511
  end
543
512
 
@@ -12,6 +12,10 @@ describe :minitest_helper do
12
12
 
13
13
  include ::Chewy::Minitest::Helpers
14
14
 
15
+ def assert_equal(expected, actual, message)
16
+ raise message unless expected == actual
17
+ end
18
+
15
19
  before do
16
20
  Chewy.massacre
17
21
  end
@@ -22,6 +26,112 @@ describe :minitest_helper do
22
26
  end
23
27
  end
24
28
 
29
+ describe 'mock_elasticsearch_response' do
30
+ let(:hits) do
31
+ [
32
+ {
33
+ '_index' => 'dummies',
34
+ '_type' => '_doc',
35
+ '_id' => '1',
36
+ '_score' => 3.14,
37
+ '_source' => source
38
+ }
39
+ ]
40
+ end
41
+
42
+ let(:source) { {'name' => 'some_name'} }
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
+ let(:unexpected_query_error_message) do
125
+ 'got {:index=>["dummies"], :body=>{:query=>{:bool=>{:filter=>{:bool=>{:must=>{:match=>{:foo=>"bar"}}, :should=>{:multi_match=>{:foo=>"bar"}}}}}}}} instead of expected query.'
126
+ end
127
+
128
+ specify do
129
+ expect { assert_elasticsearch_query(query, unexpected_query) }
130
+ .to raise_error(RuntimeError, unexpected_query_error_message)
131
+ end
132
+ end
133
+ end
134
+
25
135
  context 'assert_indexes' do
26
136
  specify 'doesn\'t fail when index updates correctly' do
27
137
  expect do
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe :build_query do
4
+ before do
5
+ stub_model(:city)
6
+ stub_index(:cities) { index_scope City }
7
+ CitiesIndex.create
8
+ end
9
+
10
+ let(:expected_query) do
11
+ {
12
+ index: ['cities'],
13
+ body: {
14
+ query: {
15
+ match: {name: 'name'}
16
+ }
17
+ }
18
+ }
19
+ end
20
+ let(:dummy_query) { {match: {name: 'name'}} }
21
+ let(:unexpected_query) { {match: {name: 'name'}} }
22
+
23
+ context 'build expected query' do
24
+ specify do
25
+ expect(CitiesIndex.query(dummy_query)).to build_query(expected_query)
26
+ end
27
+ end
28
+
29
+ context 'not to build unexpected query' do
30
+ specify do
31
+ expect(CitiesIndex.query(dummy_query)).not_to build_query(unexpected_query)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe :rspec_helper do
4
+ include ::Chewy::Rspec::Helpers
5
+
6
+ before do
7
+ stub_model(:city)
8
+ stub_index(:cities) { index_scope City }
9
+ CitiesIndex.create
10
+ end
11
+
12
+ let(:hits) do
13
+ [
14
+ {
15
+ '_index' => 'cities',
16
+ '_type' => '_doc',
17
+ '_id' => '1',
18
+ '_score' => 3.14,
19
+ '_source' => source
20
+ }
21
+ ]
22
+ end
23
+
24
+ let(:source) { {'name' => 'some_name'} }
25
+ let(:sources) { [source] }
26
+
27
+ context :mock_elasticsearch_response do
28
+ let(:raw_response) do
29
+ {
30
+ 'took' => 4,
31
+ 'timed_out' => false,
32
+ '_shards' => {
33
+ 'total' => 1,
34
+ 'successful' => 1,
35
+ 'skipped' => 0,
36
+ 'failed' => 0
37
+ },
38
+ 'hits' => {
39
+ 'total' => {
40
+ 'value' => 1,
41
+ 'relation' => 'eq'
42
+ },
43
+ 'max_score' => 1.0,
44
+ 'hits' => hits
45
+ }
46
+ }
47
+ end
48
+
49
+ specify do
50
+ mock_elasticsearch_response(CitiesIndex, raw_response)
51
+ expect(CitiesIndex.query({}).hits).to eq(hits)
52
+ end
53
+ end
54
+
55
+ context :mock_elasticsearch_response_sources do
56
+ specify do
57
+ mock_elasticsearch_response_sources(CitiesIndex, sources)
58
+ expect(CitiesIndex.query({}).hits).to eq(hits)
59
+ end
60
+ end
61
+ end
@@ -4,26 +4,29 @@ describe Chewy::Search::Parameters::Order do
4
4
  subject { described_class.new(%i[foo bar]) }
5
5
 
6
6
  describe '#initialize' do
7
- specify { expect(described_class.new.value).to eq({}) }
8
- specify { expect(described_class.new(nil).value).to eq({}) }
9
- specify { expect(described_class.new('').value).to eq({}) }
10
- specify { expect(described_class.new(42).value).to eq('42' => nil) }
11
- specify { expect(described_class.new([42, 43]).value).to eq('42' => nil, '43' => nil) }
12
- specify { expect(described_class.new(a: 1).value).to eq('a' => 1) }
13
- specify { expect(described_class.new(['', 43, {a: 1}]).value).to eq('a' => 1, '43' => nil) }
7
+ specify { expect(described_class.new.value).to eq([]) }
8
+ specify { expect(described_class.new(nil).value).to eq([]) }
9
+ specify { expect(described_class.new('').value).to eq([]) }
10
+ specify { expect(described_class.new(42).value).to eq(['42']) }
11
+ specify { expect(described_class.new([42, 43]).value).to eq(%w[42 43]) }
12
+ specify { expect(described_class.new([42, 42]).value).to eq(%w[42 42]) }
13
+ specify { expect(described_class.new([42, [43, 44]]).value).to eq(%w[42 43 44]) }
14
+ specify { expect(described_class.new(a: 1).value).to eq([{'a' => 1}]) }
15
+ specify { expect(described_class.new(['a', {a: 1}, {a: 2}]).value).to eq(['a', {'a' => 1}, {'a' => 2}]) }
16
+ specify { expect(described_class.new(['', 43, {a: 1}]).value).to eq(['43', {'a' => 1}]) }
14
17
  end
15
18
 
16
19
  describe '#replace!' do
17
20
  specify do
18
21
  expect { subject.replace!(foo: {}) }
19
22
  .to change { subject.value }
20
- .from('foo' => nil, 'bar' => nil).to('foo' => {})
23
+ .from(%w[foo bar]).to([{'foo' => {}}])
21
24
  end
22
25
 
23
26
  specify do
24
27
  expect { subject.replace!(nil) }
25
28
  .to change { subject.value }
26
- .from('foo' => nil, 'bar' => nil).to({})
29
+ .from(%w[foo bar]).to([])
27
30
  end
28
31
  end
29
32
 
@@ -31,7 +34,7 @@ describe Chewy::Search::Parameters::Order do
31
34
  specify do
32
35
  expect { subject.update!(foo: {}) }
33
36
  .to change { subject.value }
34
- .from('foo' => nil, 'bar' => nil).to('foo' => {}, 'bar' => nil)
37
+ .from(%w[foo bar]).to(['foo', 'bar', {'foo' => {}}])
35
38
  end
36
39
 
37
40
  specify { expect { subject.update!(nil) }.not_to change { subject.value } }
@@ -41,7 +44,7 @@ describe Chewy::Search::Parameters::Order do
41
44
  specify do
42
45
  expect { subject.merge!(described_class.new(foo: {})) }
43
46
  .to change { subject.value }
44
- .from('foo' => nil, 'bar' => nil).to('foo' => {}, 'bar' => nil)
47
+ .from(%w[foo bar]).to(['foo', 'bar', {'foo' => {}}])
45
48
  end
46
49
 
47
50
  specify { expect { subject.merge!(described_class.new) }.not_to change { subject.value } }
@@ -51,6 +54,7 @@ describe Chewy::Search::Parameters::Order do
51
54
  specify { expect(described_class.new.render).to be_nil }
52
55
  specify { expect(described_class.new(:foo).render).to eq(sort: ['foo']) }
53
56
  specify { expect(described_class.new([:foo, {bar: 42}, :baz]).render).to eq(sort: ['foo', {'bar' => 42}, 'baz']) }
57
+ specify { expect(described_class.new([:foo, {bar: 42}, {bar: 43}, :baz]).render).to eq(sort: ['foo', {'bar' => 42}, {'bar' => 43}, 'baz']) }
54
58
  end
55
59
 
56
60
  describe '#==' do
@@ -59,7 +63,10 @@ describe Chewy::Search::Parameters::Order do
59
63
  specify { expect(described_class.new(:foo)).not_to eq(described_class.new(:bar)) }
60
64
  specify { expect(described_class.new(%i[foo bar])).to eq(described_class.new(%i[foo bar])) }
61
65
  specify { expect(described_class.new(%i[foo bar])).not_to eq(described_class.new(%i[bar foo])) }
66
+ specify { expect(described_class.new(%i[foo foo])).not_to eq(described_class.new(%i[foo])) }
62
67
  specify { expect(described_class.new(foo: {a: 42})).to eq(described_class.new(foo: {a: 42})) }
63
68
  specify { expect(described_class.new(foo: {a: 42})).not_to eq(described_class.new(foo: {b: 42})) }
69
+ specify { expect(described_class.new(['foo', {'foo' => 42}])).not_to eq(described_class.new([{'foo' => 42}, 'foo'])) }
70
+ specify { expect(described_class.new([{'foo' => 42}, {'foo' => 43}])).not_to eq(described_class.new([{'foo' => 43}, {'foo' => 42}])) }
64
71
  end
65
72
  end
@@ -13,7 +13,7 @@ describe Chewy::Search::Parameters do
13
13
 
14
14
  specify { expect(subject.storages[:limit]).to equal(limit) }
15
15
  specify { expect(subject.storages[:limit].value).to eq(3) }
16
- specify { expect(subject.storages[:order].value).to eq('foo' => nil) }
16
+ specify { expect(subject.storages[:order].value).to eq(['foo']) }
17
17
 
18
18
  specify { expect { described_class.new(offset: limit) }.to raise_error(TypeError) }
19
19
  end
@@ -177,7 +177,7 @@ describe Chewy::Search::Request do
177
177
  describe '#order' do
178
178
  specify { expect(subject.order(:foo).render[:body]).to include(sort: ['foo']) }
179
179
  specify { expect(subject.order(foo: 42).order(nil).render[:body]).to include(sort: ['foo' => 42]) }
180
- specify { expect(subject.order(foo: 42).order(foo: 43).render[:body]).to include(sort: ['foo' => 43]) }
180
+ specify { expect(subject.order(foo: 42).order(foo: 43).render[:body]).to include(sort: [{'foo' => 42}, {'foo' => 43}]) }
181
181
  specify { expect(subject.order(:foo).order(:bar, :baz).render[:body]).to include(sort: %w[foo bar baz]) }
182
182
  specify { expect(subject.order(nil).render[:body]).to be_blank }
183
183
  specify { expect { subject.order(:foo) }.not_to change { subject.render } }
data/spec/spec_helper.rb CHANGED
@@ -8,7 +8,6 @@ require 'rspec/its'
8
8
  require 'rspec/collection_matchers'
9
9
 
10
10
  require 'timecop'
11
- require 'ruby-progressbar'
12
11
 
13
12
  Kaminari::Hooks.init if defined?(::Kaminari::Hooks)
14
13
 
@@ -1,6 +1,6 @@
1
1
  require 'database_cleaner'
2
2
 
3
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file::memory:?cache=shared', pool: 1)
3
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file::memory:?cache=shared', pool: 10)
4
4
  ActiveRecord::Base.logger = Logger.new('/dev/null')
5
5
  if ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks)
6
6
  ActiveRecord::Base.raise_in_transactional_callbacks = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chewy
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.1
4
+ version: 7.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toptal, LLC
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-05-11 00:00:00.000000000 Z
12
+ date: 2021-05-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: database_cleaner
@@ -185,14 +185,14 @@ dependencies:
185
185
  requirements:
186
186
  - - ">="
187
187
  - !ruby/object:Gem::Version
188
- version: 6.3.0
188
+ version: 7.12.0
189
189
  type: :runtime
190
190
  prerelease: false
191
191
  version_requirements: !ruby/object:Gem::Requirement
192
192
  requirements:
193
193
  - - ">="
194
194
  - !ruby/object:Gem::Version
195
- version: 6.3.0
195
+ version: 7.12.0
196
196
  - !ruby/object:Gem::Dependency
197
197
  name: elasticsearch-dsl
198
198
  requirement: !ruby/object:Gem::Requirement
@@ -207,20 +207,6 @@ dependencies:
207
207
  - - ">="
208
208
  - !ruby/object:Gem::Version
209
209
  version: '0'
210
- - !ruby/object:Gem::Dependency
211
- name: ruby-progressbar
212
- requirement: !ruby/object:Gem::Requirement
213
- requirements:
214
- - - ">="
215
- - !ruby/object:Gem::Version
216
- version: '0'
217
- type: :runtime
218
- prerelease: false
219
- version_requirements: !ruby/object:Gem::Requirement
220
- requirements:
221
- - - ">="
222
- - !ruby/object:Gem::Version
223
- version: '0'
224
210
  description: Chewy provides functionality for Elasticsearch index handling, documents
225
211
  import mappings and chainable query DSL
226
212
  email:
@@ -272,7 +258,6 @@ files:
272
258
  - lib/chewy/index/import/bulk_request.rb
273
259
  - lib/chewy/index/import/journal_builder.rb
274
260
  - lib/chewy/index/import/routine.rb
275
- - lib/chewy/index/import/thread_safe_progress_bar.rb
276
261
  - lib/chewy/index/mapping.rb
277
262
  - lib/chewy/index/observe.rb
278
263
  - lib/chewy/index/settings.rb
@@ -290,6 +275,8 @@ files:
290
275
  - lib/chewy/rake_helper.rb
291
276
  - lib/chewy/repository.rb
292
277
  - lib/chewy/rspec.rb
278
+ - lib/chewy/rspec/build_query.rb
279
+ - lib/chewy/rspec/helpers.rb
293
280
  - lib/chewy/rspec/update_index.rb
294
281
  - lib/chewy/runtime.rb
295
282
  - lib/chewy/runtime/version.rb
@@ -379,6 +366,8 @@ files:
379
366
  - spec/chewy/multi_search_spec.rb
380
367
  - spec/chewy/rake_helper_spec.rb
381
368
  - spec/chewy/repository_spec.rb
369
+ - spec/chewy/rspec/build_query_spec.rb
370
+ - spec/chewy/rspec/helpers_spec.rb
382
371
  - spec/chewy/rspec/update_index_spec.rb
383
372
  - spec/chewy/runtime/version_spec.rb
384
373
  - spec/chewy/runtime_spec.rb
@@ -487,6 +476,8 @@ test_files:
487
476
  - spec/chewy/multi_search_spec.rb
488
477
  - spec/chewy/rake_helper_spec.rb
489
478
  - spec/chewy/repository_spec.rb
479
+ - spec/chewy/rspec/build_query_spec.rb
480
+ - spec/chewy/rspec/helpers_spec.rb
490
481
  - spec/chewy/rspec/update_index_spec.rb
491
482
  - spec/chewy/runtime/version_spec.rb
492
483
  - spec/chewy/runtime_spec.rb
@@ -1,40 +0,0 @@
1
- module Chewy
2
- class Index
3
- module Import
4
- # This class performs the threading for parallel import to avoid concurrency during progressbar output.
5
- #
6
- # @see Chewy::Type::Import::ClassMethods#import with `parallel: true` option
7
- class ThreadSafeProgressBar
8
- def initialize(enabled)
9
- @enabled = enabled
10
-
11
- return unless @enabled
12
-
13
- @mutex = Mutex.new
14
- @released = false
15
- @progressbar = ProgressBar.create total: nil
16
- Thread.new do
17
- ActiveRecord::Base.connection_pool.with_connection do
18
- @mutex.synchronize { @released = true }
19
- @progressbar.total = yield
20
- end
21
- end
22
- end
23
-
24
- def increment(value)
25
- return unless @enabled
26
-
27
- @mutex.synchronize do
28
- @progressbar.progress += value
29
- end
30
- end
31
-
32
- def wait_until_ready
33
- return true unless @enabled
34
-
35
- @mutex.synchronize { @released } until @released
36
- end
37
- end
38
- end
39
- end
40
- end