chewy 7.3.6 → 7.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -28
  3. data/.rubocop.yml +1 -1
  4. data/CHANGELOG.md +18 -1
  5. data/Gemfile +4 -4
  6. data/README.md +24 -1
  7. data/chewy.gemspec +3 -17
  8. data/gemfiles/base.gemfile +12 -0
  9. data/gemfiles/rails.6.1.activerecord.gemfile +2 -1
  10. data/gemfiles/rails.7.0.activerecord.gemfile +2 -1
  11. data/gemfiles/rails.7.1.activerecord.gemfile +2 -1
  12. data/lib/chewy/config.rb +15 -11
  13. data/lib/chewy/elastic_client.rb +31 -0
  14. data/lib/chewy/fields/root.rb +1 -1
  15. data/lib/chewy/index/adapter/active_record.rb +1 -1
  16. data/lib/chewy/index/adapter/object.rb +3 -3
  17. data/lib/chewy/index/adapter/orm.rb +2 -2
  18. data/lib/chewy/index/import/bulk_builder.rb +2 -2
  19. data/lib/chewy/index/import.rb +2 -2
  20. data/lib/chewy/index/observe/active_record_methods.rb +1 -1
  21. data/lib/chewy/index/syncer.rb +1 -1
  22. data/lib/chewy/minitest/search_index_receiver.rb +3 -1
  23. data/lib/chewy/rake_helper.rb +3 -3
  24. data/lib/chewy/rspec/update_index.rb +3 -3
  25. data/lib/chewy/runtime/version.rb +1 -1
  26. data/lib/chewy/search/parameters/indices.rb +1 -1
  27. data/lib/chewy/search/parameters/storage.rb +1 -1
  28. data/lib/chewy/search/parameters.rb +3 -3
  29. data/lib/chewy/search.rb +6 -4
  30. data/lib/chewy/strategy/delayed_sidekiq/scheduler.rb +3 -0
  31. data/lib/chewy/strategy/delayed_sidekiq.rb +13 -0
  32. data/lib/chewy/version.rb +1 -1
  33. data/lib/chewy.rb +3 -7
  34. data/spec/chewy/elastic_client_spec.rb +26 -0
  35. data/spec/chewy/index/actions_spec.rb +4 -4
  36. data/spec/chewy/index/import/bulk_builder_spec.rb +3 -3
  37. data/spec/chewy/index/import_spec.rb +3 -3
  38. data/spec/chewy/minitest/helpers_spec.rb +1 -1
  39. data/spec/chewy/minitest/search_index_receiver_spec.rb +6 -4
  40. data/spec/chewy/rake_helper_spec.rb +4 -4
  41. data/spec/chewy/rspec/helpers_spec.rb +1 -1
  42. data/spec/chewy/search/pagination/kaminari_examples.rb +1 -1
  43. data/spec/chewy/search/pagination/kaminari_spec.rb +1 -1
  44. data/spec/chewy/strategy/active_job_spec.rb +8 -8
  45. data/spec/chewy/strategy/delayed_sidekiq_spec.rb +12 -0
  46. data/spec/chewy/strategy/lazy_sidekiq_spec.rb +10 -10
  47. data/spec/chewy/strategy/sidekiq_spec.rb +4 -4
  48. data/spec/chewy_spec.rb +7 -4
  49. data/spec/spec_helper.rb +1 -1
  50. metadata +8 -269
  51. data/gemfiles/rails.5.2.activerecord.gemfile +0 -11
  52. data/gemfiles/rails.6.0.activerecord.gemfile +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5405b97585dccb630ef95340245a390ff7ffe19a1a27e57a35b4f4d6844e2e0
4
- data.tar.gz: 91570a2fd199d511bf40caf473d8000504cae38a4bb4b68c6f767913033f7234
3
+ metadata.gz: 1b939ad8c84f1499caf873e2db0ba62794b785da0297604a38404c0f4f68a930
4
+ data.tar.gz: bba3a09f52a65c3433b385c227c2f900645b145fba18e11737d7a9b2958d51ef
5
5
  SHA512:
6
- metadata.gz: 8441a05d5a3c55834f7380a1e10b3acb4f01f17b6cafc45e3ccead13f0d7c2a6485447c2bc8461ae5c91b37b36c4d57f140f76cb993ca63777195d64237d8432
7
- data.tar.gz: 3571db3d5fa632d6ee9c10105578ca8f805090e375372f1ad98a192dca440536f27559be2439d7e75c8ab833f596fc61758d464696ec4ee47942ff29fbffa6d5
6
+ metadata.gz: cb4f984274557d91d9d4d08306516ca4b0592bf97de3b3432585bfa9da14906d64d809da7803f19f36ba908cd8623843398e30bc78db22951cfb73015bf60a4f
7
+ data.tar.gz: 02ecef485783e555bd112240d74c75832779b8415aded37b8eb527357729e78053caead1615928fd1d54fa053a146779bb281d2bdf9f26f448c1ee680fea9bee
@@ -11,39 +11,13 @@ on:
11
11
  ]
12
12
 
13
13
  jobs:
14
- ruby-2:
15
- runs-on: ubuntu-latest
16
- strategy:
17
- fail-fast: false
18
- matrix:
19
- ruby: [2.6, 2.7]
20
- gemfile: [rails.5.2.activerecord, rails.6.0.activerecord, rails.6.1.activerecord]
21
- name: ${{ matrix.ruby }}-${{ matrix.gemfile }}
22
-
23
- env:
24
- BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
25
-
26
- steps:
27
- - uses: actions/checkout@v4
28
- - uses: ruby/setup-ruby@v1
29
- with:
30
- ruby-version: ${{ matrix.ruby }}
31
- bundler-cache: true
32
- - name: Run Elasticsearch
33
- uses: elastic/elastic-github-actions/elasticsearch@9de0f78f306e4ebc0838f057e6b754364685e759
34
- with:
35
- stack-version: 7.10.1
36
- port: 9250
37
- - name: Tests
38
- run: bundle exec rspec
39
-
40
14
  ruby-3:
41
15
  runs-on: ubuntu-latest
42
16
  strategy:
43
17
  fail-fast: false
44
18
  matrix:
45
19
  ruby: [ '3.0', '3.1', '3.2' ]
46
- gemfile: [ rails.6.1.activerecord, rails.7.0.activerecord, rails.7.1.activerecord ]
20
+ gemfile: [rails.6.1.activerecord, rails.7.0.activerecord, rails.7.1.activerecord]
47
21
  name: ${{ matrix.ruby }}-${{ matrix.gemfile }}
48
22
 
49
23
  env:
@@ -69,6 +43,6 @@ jobs:
69
43
  - uses: actions/checkout@v4
70
44
  - uses: ruby/setup-ruby@v1
71
45
  with:
72
- ruby-version: 2.7
46
+ ruby-version: 3.0
73
47
  bundler-cache: true
74
48
  - run: bundle exec rubocop --format simple
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ inherit_from: .rubocop_todo.yml
2
2
 
3
3
  AllCops:
4
4
  NewCops: enable
5
- TargetRubyVersion: 2.6
5
+ TargetRubyVersion: 3.0
6
6
 
7
7
  Layout/AccessModifierIndentation:
8
8
  EnforcedStyle: outdent
data/CHANGELOG.md CHANGED
@@ -8,7 +8,24 @@
8
8
 
9
9
  ### Bugs Fixed
10
10
 
11
- ## 7.3.5 (2023-12-13)
11
+ ## 7.5.0 (2023-01-15)
12
+
13
+ ### New Features
14
+
15
+ * [#894](https://github.com/toptal/chewy/pull/894): Way of cleaning redis from artifacts left by `delayed_sidekiq` strategy which could potentially cause flaky tests. ([@Drowze](https://github.com/Drowze))
16
+ * [#919](https://github.com/toptal/chewy/pull/919): Add pre-request filter ([@konalegi][https://github.com/konalegi])
17
+
18
+ ## 7.4.0 (2023-12-13)
19
+
20
+ ### New Features
21
+
22
+ ### Changes
23
+
24
+ * [#911](https://github.com/toptal/chewy/pull/911): Remove ruby 2.x. ([@konalegi][https://github.com/konalegi])
25
+
26
+ ### Bugs Fixed
27
+
28
+ ## 7.3.6 (2023-12-13)
12
29
 
13
30
  ### New Features
14
31
 
data/Gemfile CHANGED
@@ -1,7 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gemspec
4
-
5
3
  gem 'activerecord'
6
4
 
7
5
  gem 'activejob', require: false
@@ -18,5 +16,7 @@ gem 'guard-rspec'
18
16
  gem 'redcarpet'
19
17
  gem 'yard'
20
18
 
21
- gem 'rexml' if RUBY_VERSION >= '3.0.0'
22
- gem 'ruby2_keywords' if RUBY_VERSION < '2.7'
19
+ gem 'rexml'
20
+
21
+ eval_gemfile 'gemfiles/base.gemfile'
22
+ gemspec
data/README.md CHANGED
@@ -43,7 +43,7 @@ Or install it yourself as:
43
43
 
44
44
  ### Ruby
45
45
 
46
- Chewy is compatible with MRI 2.6-3.0¹.
46
+ Chewy is compatible with MRI 3.0-3.2¹.
47
47
 
48
48
  > ¹ Ruby 3 is only supported with Rails 6.1
49
49
 
@@ -848,6 +848,12 @@ Explicit call of the reindex using `:delayed_sidekiq` strategy with `:update_fie
848
848
  CitiesIndex.import([1, 2, 3], update_fields: [:name], strategy: :delayed_sidekiq)
849
849
  ```
850
850
 
851
+ While running tests with delayed_sidekiq strategy and Sidekiq is using a real redis instance that is NOT cleaned up in between tests (via e.g. `Sidekiq.redis(&:flushdb)`), you'll want to cleanup some redis keys in between tests to avoid state leaking and flaky tests. Chewy provides a convenience method for that:
852
+ ```ruby
853
+ # it might be a good idea to also add to your testing setup, e.g.: a rspec `before` hook
854
+ Chewy::Strategy::DelayedSidekiq.clear_timechunks!
855
+ ```
856
+
851
857
  #### `:active_job`
852
858
 
853
859
  This does the same thing as `:atomic`, but using ActiveJob. This will inherit the ActiveJob configuration settings including the `active_job.queue_adapter` setting for the environment. Patch `Chewy::Strategy::ActiveJob::Worker` for index updates improving.
@@ -1275,6 +1281,23 @@ If you use `DatabaseCleaner` in your tests with [the `transaction` strategy](htt
1275
1281
  Chewy.use_after_commit_callbacks = !Rails.env.test?
1276
1282
  ```
1277
1283
 
1284
+ ### Pre-request Filter
1285
+
1286
+ Should you need to inspect the query prior to it being dispatched to ElasticSearch during any queries, you can use the `before_es_request_filter`. `before_es_request_filter` is a callable object, as demonstrated below:
1287
+
1288
+ ```ruby
1289
+ Chewy.before_es_request_filter = -> (method_name, args, kw_args) { ... }
1290
+ ```
1291
+
1292
+ While using the `before_es_request_filter`, please consider the following:
1293
+
1294
+ * `before_es_request_filter` acts as a simple proxy before any request made via the `ElasticSearch::Client`. The arguments passed to this filter include:
1295
+ * `method_name` - The name of the method being called. Examples are search, count, bulk and etc.
1296
+ * `args` and `kw_args` - These are the positional arguments provided in the method call.
1297
+ * The operation is synchronous, so avoid executing any heavy or time-consuming operations within the filter to prevent performance degradation.
1298
+ * The return value of the proc is disregarded. This filter is intended for inspection or modification of the query rather than generating a response.
1299
+ * Any exception raised inside the callback will propagate upward and halt the execution of the query. It is essential to handle potential errors adequately to ensure the stability of your search functionality.
1300
+
1278
1301
  ## Contributing
1279
1302
 
1280
1303
  1. Fork it (http://github.com/toptal/chewy/fork)
data/chewy.gemspec CHANGED
@@ -2,7 +2,7 @@ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'chewy/version'
4
4
 
5
- Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
5
+ Gem::Specification.new do |spec|
6
6
  spec.name = 'chewy'
7
7
  spec.version = Chewy::VERSION
8
8
  spec.authors = ['Toptal, LLC', 'pyromaniac']
@@ -14,24 +14,10 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
14
14
 
15
15
  spec.files = `git ls-files`.split($RS)
16
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
17
  spec.require_paths = ['lib']
19
18
 
20
- spec.add_development_dependency 'database_cleaner'
21
- spec.add_development_dependency 'elasticsearch-extensions'
22
- spec.add_development_dependency 'mock_redis'
23
- spec.add_development_dependency 'rake'
24
- spec.add_development_dependency 'rspec', '>= 3.7.0'
25
- spec.add_development_dependency 'rspec-collection_matchers'
26
- spec.add_development_dependency 'rspec-its'
27
- spec.add_development_dependency 'rubocop', '1.11'
28
- spec.add_development_dependency 'sqlite3'
29
- spec.add_development_dependency 'timecop'
30
-
31
- spec.add_development_dependency 'method_source'
32
- spec.add_development_dependency 'unparser'
33
-
34
- spec.add_dependency 'activesupport', '>= 5.2'
19
+ spec.add_dependency 'activesupport', '>= 5.2' # Remove with major version bump, 8.x
35
20
  spec.add_dependency 'elasticsearch', '>= 7.12.0', '< 7.14.0'
36
21
  spec.add_dependency 'elasticsearch-dsl'
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
37
23
  end
@@ -0,0 +1,12 @@
1
+ gem 'database_cleaner'
2
+ gem 'elasticsearch-extensions'
3
+ gem 'method_source'
4
+ gem 'mock_redis'
5
+ gem 'rake'
6
+ gem 'rspec', '>= 3.7.0'
7
+ gem 'rspec-collection_matchers'
8
+ gem 'rspec-its'
9
+ gem 'rubocop', '1.48'
10
+ gem 'sqlite3'
11
+ gem 'timecop'
12
+ gem 'unparser'
@@ -8,6 +8,7 @@ gem 'parallel', require: false
8
8
  gem 'rspec_junit_formatter', '~> 0.4.1'
9
9
  gem 'sidekiq', require: false
10
10
 
11
- gem 'rexml' if RUBY_VERSION >= '3.0.0'
11
+ gem 'rexml'
12
12
 
13
13
  gemspec path: '../'
14
+ eval_gemfile 'base.gemfile'
@@ -8,6 +8,7 @@ gem 'parallel', require: false
8
8
  gem 'rspec_junit_formatter', '~> 0.4.1'
9
9
  gem 'sidekiq', require: false
10
10
 
11
- gem 'rexml' if RUBY_VERSION >= '3.0.0'
11
+ gem 'rexml'
12
12
 
13
13
  gemspec path: '../'
14
+ eval_gemfile 'base.gemfile'
@@ -8,6 +8,7 @@ gem 'parallel', require: false
8
8
  gem 'rspec_junit_formatter', '~> 0.4.1'
9
9
  gem 'sidekiq', require: false
10
10
 
11
- gem 'rexml' if RUBY_VERSION >= '3.0.0'
11
+ gem 'rexml'
12
12
 
13
13
  gemspec path: '../'
14
+ eval_gemfile 'base.gemfile'
data/lib/chewy/config.rb CHANGED
@@ -38,7 +38,9 @@ module Chewy
38
38
  # for type mappings like `_all`.
39
39
  :default_root_options,
40
40
  # Default field type for any field in any Chewy type. Defaults to 'text'.
41
- :default_field_type
41
+ :default_field_type,
42
+ # Callback called on each search request to be done into ES
43
+ :before_es_request_filter
42
44
 
43
45
  attr_reader :transport_logger, :transport_tracer,
44
46
  # Chewy search request DSL base class, used by every index.
@@ -127,17 +129,19 @@ module Chewy
127
129
  private
128
130
 
129
131
  def yaml_settings
130
- @yaml_settings ||= begin
131
- if defined?(Rails::VERSION)
132
- file = Rails.root.join('config', 'chewy.yml')
132
+ @yaml_settings ||= build_yaml_settings || {}
133
+ end
133
134
 
134
- if File.exist?(file)
135
- yaml = ERB.new(File.read(file)).result
136
- hash = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(yaml) : YAML.load(yaml) # rubocop:disable Security/YAMLLoad
137
- hash[Rails.env].try(:deep_symbolize_keys) if hash
138
- end
139
- end || {}
140
- end
135
+ def build_yaml_settings
136
+ return unless defined?(Rails::VERSION)
137
+
138
+ file = Rails.root.join('config', 'chewy.yml')
139
+
140
+ return unless File.exist?(file)
141
+
142
+ yaml = ERB.new(File.read(file)).result
143
+ hash = YAML.unsafe_load(yaml)
144
+ hash[Rails.env].try(:deep_symbolize_keys) if hash
141
145
  end
142
146
 
143
147
  def build_search_class(base)
@@ -0,0 +1,31 @@
1
+ module Chewy
2
+ # Replacement for Chewy.client
3
+ class ElasticClient
4
+ def self.build_es_client(configuration = Chewy.configuration)
5
+ client_configuration = configuration.deep_dup
6
+ client_configuration.delete(:prefix) # used by Chewy, not relevant to Elasticsearch::Client
7
+ block = client_configuration[:transport_options].try(:delete, :proc)
8
+ ::Elasticsearch::Client.new(client_configuration, &block)
9
+ end
10
+
11
+ def initialize(elastic_client = self.class.build_es_client)
12
+ @elastic_client = elastic_client
13
+ end
14
+
15
+ private
16
+
17
+ def method_missing(name, *args, **kwargs, &block)
18
+ inspect_payload(name, args, kwargs)
19
+
20
+ @elastic_client.__send__(name, *args, **kwargs, &block)
21
+ end
22
+
23
+ def respond_to_missing?(name, _include_private = false)
24
+ @elastic_client.respond_to?(name) || super
25
+ end
26
+
27
+ def inspect_payload(name, args, kwargs)
28
+ Chewy.config.before_es_request_filter&.call(name, args, kwargs)
29
+ end
30
+ end
31
+ end
@@ -27,7 +27,7 @@ module Chewy
27
27
  mappings[name]
28
28
  end
29
29
 
30
- ruby2_keywords def dynamic_template(*args)
30
+ def dynamic_template(*args)
31
31
  options = args.extract_options!.deep_symbolize_keys
32
32
  if args.first
33
33
  template_name = :"template_#{dynamic_templates.count.next}"
@@ -6,7 +6,7 @@ module Chewy
6
6
  class ActiveRecord < Orm
7
7
  def self.accepts?(target)
8
8
  defined?(::ActiveRecord::Base) && (
9
- target.is_a?(Class) && target < ::ActiveRecord::Base ||
9
+ (target.is_a?(Class) && target < ::ActiveRecord::Base) ||
10
10
  target.is_a?(::ActiveRecord::Relation))
11
11
  end
12
12
 
@@ -85,7 +85,7 @@ module Chewy
85
85
  # @param args [Array<#to_json>]
86
86
  # @option options [Integer] :batch_size import processing batch size
87
87
  # @return [true, false]
88
- ruby2_keywords def import(*args, &block)
88
+ def import(*args, &block)
89
89
  collection, options = import_args(*args)
90
90
  import_objects(collection, options, &block)
91
91
  end
@@ -113,7 +113,7 @@ module Chewy
113
113
  # end
114
114
  #
115
115
  # @see Chewy::Index::Adapter::Base#import_fields
116
- ruby2_keywords def import_fields(*args, &block)
116
+ def import_fields(*args, &block)
117
117
  return enum_for(:import_fields, *args) unless block_given?
118
118
 
119
119
  options = args.extract_options!
@@ -139,7 +139,7 @@ module Chewy
139
139
  # For the Object adapter returns the objects themselves in batches.
140
140
  #
141
141
  # @see Chewy::Index::Adapter::Base#import_references
142
- ruby2_keywords def import_references(*args, &block)
142
+ def import_references(*args, &block)
143
143
  return enum_for(:import_references, *args) unless block_given?
144
144
 
145
145
  collection, options = import_args(*args)
@@ -72,7 +72,7 @@ module Chewy
72
72
  # # or
73
73
  # UsersIndex.import users.map(&:id) # user ids will be deleted from index
74
74
  #
75
- ruby2_keywords def import(*args, &block)
75
+ def import(*args, &block)
76
76
  collection, options = import_args(*args)
77
77
 
78
78
  if !collection.is_a?(relation_class) || options[:direct_import]
@@ -82,7 +82,7 @@ module Chewy
82
82
  end
83
83
  end
84
84
 
85
- ruby2_keywords def import_fields(*args, &block)
85
+ def import_fields(*args, &block)
86
86
  return enum_for(:import_fields, *args) unless block_given?
87
87
 
88
88
  collection, options = import_args(*args)
@@ -162,12 +162,12 @@ module Chewy
162
162
  .filter(ids: {values: ids_for_cache})
163
163
  .order('_doc')
164
164
  .pluck(:_id, :_routing, join_field)
165
- .map do |id, routing, join|
165
+ .to_h do |id, routing, join|
166
166
  [
167
167
  id,
168
168
  {routing: routing, parent_id: join['parent']}
169
169
  ]
170
- end.to_h
170
+ end
171
171
  end
172
172
 
173
173
  def existing_routing(id)
@@ -72,7 +72,7 @@ module Chewy
72
72
  # @option options [true, false] update_failover enables full objects reimport in cases of partial update errors, `true` by default
73
73
  # @option options [true, Integer, Hash] parallel enables parallel import processing with the Parallel gem, accepts the number of workers or any Parallel gem acceptable options
74
74
  # @return [true, false] false in case of errors
75
- ruby2_keywords def import(*args)
75
+ def import(*args)
76
76
  intercept_import_using_strategy(*args).blank?
77
77
  end
78
78
 
@@ -83,7 +83,7 @@ module Chewy
83
83
  # in case of any import errors.
84
84
  #
85
85
  # @raise [Chewy::ImportFailed] in case of errors
86
- ruby2_keywords def import!(*args)
86
+ def import!(*args)
87
87
  errors = intercept_import_using_strategy(*args)
88
88
 
89
89
  raise Chewy::ImportFailed.new(self, errors) if errors.present?
@@ -71,7 +71,7 @@ module Chewy
71
71
  end
72
72
  end
73
73
 
74
- ruby2_keywords def update_index(type_name, *args, &block)
74
+ def update_index(type_name, *args, &block)
75
75
  callback_options = Observe.extract_callback_options!(args)
76
76
  update_proc = Observe.update_proc(type_name, *args, &block)
77
77
  callback = Chewy::Index::Observe::Callback.new(update_proc, callback_options)
@@ -27,7 +27,7 @@ module Chewy
27
27
  # @see Chewy::Index::Actions::ClassMethods#sync
28
28
  class Syncer
29
29
  DEFAULT_SYNC_BATCH_SIZE = 20_000
30
- ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/.freeze
30
+ ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
31
31
  OUTDATED_IDS_WORKER = lambda do |outdated_sync_field_type, source_data_hash, index, total, index_data|
32
32
  ::Process.setproctitle("chewy [#{index}]: sync outdated calculation (#{::Parallel.worker_number + 1}/#{total})") if index
33
33
  index_data.each_with_object([]) do |(id, index_sync_value), result|
@@ -6,6 +6,8 @@
6
6
  # The class will capture the data from the *param on the Chewy::Index.bulk method and
7
7
  # aggregate the data for test analysis.
8
8
  class SearchIndexReceiver
9
+ MUTATION_FOR_CLASS = Struct.new(:indexes, :deletes, keyword_init: true)
10
+
9
11
  def initialize
10
12
  @mutations = {}
11
13
  end
@@ -71,6 +73,6 @@ private
71
73
  # @param index [Chewy::Index] the index to fetch.
72
74
  # @return [#indexes, #deletes] an object with a list of indexes and a list of deletes.
73
75
  def mutation_for(index)
74
- @mutations[index] ||= OpenStruct.new(indexes: [], deletes: [])
76
+ @mutations[index] ||= MUTATION_FOR_CLASS.new(indexes: [], deletes: [])
75
77
  end
76
78
  end
@@ -347,9 +347,9 @@ module Chewy
347
347
  return if journal_exists?
348
348
 
349
349
  output.puts "############################################################\n" \
350
- "WARN: You are risking to lose some changes during the reset.\n" \
351
- " Please consider enabling journaling.\n" \
352
- " See https://github.com/toptal/chewy#journaling\n" \
350
+ "WARN: You are risking to lose some changes during the reset.\n " \
351
+ "Please consider enabling journaling.\n " \
352
+ "See https://github.com/toptal/chewy#journaling\n" \
353
353
  '############################################################'
354
354
  end
355
355
 
@@ -108,7 +108,7 @@ RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:dis
108
108
  params_matcher = @no_refresh ? has_entry(refresh: false) : any_parameters
109
109
  Chewy::Index::Import::BulkRequest.stubs(:new).with(index, params_matcher).returns(mock_bulk_request)
110
110
  else
111
- mocked_already = ::RSpec::Mocks.space.proxy_for(Chewy::Index::Import::BulkRequest).method_double_if_exists_for_message(:new)
111
+ mocked_already = RSpec::Mocks.space.proxy_for(Chewy::Index::Import::BulkRequest).method_double_if_exists_for_message(:new)
112
112
  allow(Chewy::Index::Import::BulkRequest).to receive(:new).and_call_original unless mocked_already
113
113
  params_matcher = @no_refresh ? hash_including(refresh: false) : any_args
114
114
  allow(Chewy::Index::Import::BulkRequest).to receive(:new).with(index, params_matcher).and_return(mock_bulk_request)
@@ -220,7 +220,7 @@ RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:dis
220
220
  expected_count = options[:times] || options[:count]
221
221
  expected_attributes = (options[:with] || options[:attributes] || {}).deep_symbolize_keys
222
222
 
223
- args.flatten.map do |document|
223
+ args.flatten.to_h do |document|
224
224
  id = document.respond_to?(:id) ? document.id.to_s : document.to_s
225
225
  [id, {
226
226
  document: document,
@@ -229,7 +229,7 @@ RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:dis
229
229
  real_count: 0,
230
230
  real_attributes: {}
231
231
  }]
232
- end.to_h
232
+ end
233
233
  end
234
234
 
235
235
  def compare_attributes(expected, real)
@@ -5,7 +5,7 @@ module Chewy
5
5
  attr_reader :major, :minor, :patch
6
6
 
7
7
  def initialize(version)
8
- @major, @minor, @patch = *(version.to_s.split('.', 3) + [0] * 3).first(3).map(&:to_i)
8
+ @major, @minor, @patch = *(version.to_s.split('.', 3) + ([0] * 3)).first(3).map(&:to_i)
9
9
  end
10
10
 
11
11
  def to_s
@@ -17,7 +17,7 @@ module Chewy
17
17
  # @param other [Chewy::Search::Parameters::Storage] any storage instance
18
18
  # @return [true, false] the result of comparison
19
19
  def ==(other)
20
- super || other.class == self.class && other.render == render
20
+ super || (other.class == self.class && other.render == render)
21
21
  end
22
22
 
23
23
  # Just adds indices to indices.
@@ -35,7 +35,7 @@ module Chewy
35
35
  # @param other [Chewy::Search::Parameters::Storage] any storage instance
36
36
  # @return [true, false] the result of comparision
37
37
  def ==(other)
38
- super || other.class == self.class && other.value == value
38
+ super || (other.class == self.class && other.value == value)
39
39
  end
40
40
 
41
41
  # Replaces current value with normalized provided one. Doesn't
@@ -1,5 +1,5 @@
1
- Dir.glob(File.join(File.dirname(__FILE__), 'parameters', 'concerns', '*.rb')).sort.each { |f| require f }
2
- Dir.glob(File.join(File.dirname(__FILE__), 'parameters', '*.rb')).sort.each { |f| require f }
1
+ Dir.glob(File.join(File.dirname(__FILE__), 'parameters', 'concerns', '*.rb')).each { |f| require f }
2
+ Dir.glob(File.join(File.dirname(__FILE__), 'parameters', '*.rb')).each { |f| require f }
3
3
 
4
4
  module Chewy
5
5
  module Search
@@ -53,7 +53,7 @@ module Chewy
53
53
  # @param other [Object] any object
54
54
  # @return [true, false]
55
55
  def ==(other)
56
- super || other.is_a?(self.class) && compare_storages(other)
56
+ super || (other.is_a?(self.class) && compare_storages(other))
57
57
  end
58
58
 
59
59
  # Clones the specified storage, performs the operation
data/lib/chewy/search.rb CHANGED
@@ -56,7 +56,7 @@ module Chewy
56
56
  #
57
57
  # @example
58
58
  # PlacesIndex.query(match: {name: 'Moscow'})
59
- ruby2_keywords def method_missing(name, *args, &block)
59
+ def method_missing(name, *args, &block)
60
60
  if search_class::DELEGATED_METHODS.include?(name)
61
61
  all.send(name, *args, &block)
62
62
  else
@@ -84,10 +84,12 @@ module Chewy
84
84
  def delegate_scoped(source, destination, methods)
85
85
  methods.each do |method|
86
86
  destination.class_eval do
87
- define_method method do |*args, &block|
88
- scoping { source.public_send(method, *args, &block) }
87
+ define_method method do |*args, **kwargs, &block|
88
+ scoping do
89
+ source.public_send(method, *args, **kwargs, &block)
90
+ end
89
91
  end
90
- ruby2_keywords method
92
+ method
91
93
  end
92
94
  end
93
95
  end
@@ -18,6 +18,7 @@ module Chewy
18
18
  DEFAULT_MARGIN = 2
19
19
  DEFAULT_QUEUE = 'chewy'
20
20
  KEY_PREFIX = 'chewy:delayed_sidekiq'
21
+ ALL_SETS_KEY = "#{KEY_PREFIX}:all_sets".freeze
21
22
  FALLBACK_FIELDS = 'all'
22
23
  FIELDS_IDS_SEPARATOR = ';'
23
24
  IDS_SEPARATOR = ','
@@ -68,8 +69,10 @@ module Chewy
68
69
  ::Sidekiq.redis do |redis|
69
70
  # warning: Redis#sadd will always return an Integer in Redis 5.0.0. Use Redis#sadd? instead
70
71
  if redis.respond_to?(:sadd?)
72
+ redis.sadd?(ALL_SETS_KEY, timechunks_key)
71
73
  redis.sadd?(timechunk_key, serialize_data)
72
74
  else
75
+ redis.sadd(ALL_SETS_KEY, timechunks_key)
73
76
  redis.sadd(timechunk_key, serialize_data)
74
77
  end
75
78
 
@@ -5,6 +5,19 @@ module Chewy
5
5
  class DelayedSidekiq < Sidekiq
6
6
  require_relative 'delayed_sidekiq/scheduler'
7
7
 
8
+ # cleanup the redis sets used internally. Useful mainly in tests to avoid
9
+ # leak and potential flaky tests.
10
+ def self.clear_timechunks!
11
+ ::Sidekiq.redis do |redis|
12
+ timechunk_sets = redis.smembers(Chewy::Strategy::DelayedSidekiq::Scheduler::ALL_SETS_KEY)
13
+ break if timechunk_sets.empty?
14
+
15
+ redis.pipelined do |pipeline|
16
+ timechunk_sets.each { |set| pipeline.del(set) }
17
+ end
18
+ end
19
+ end
20
+
8
21
  def leave
9
22
  @stash.each do |type, ids|
10
23
  next if ids.empty?
data/lib/chewy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Chewy
2
- VERSION = '7.3.6'.freeze
2
+ VERSION = '7.5.0'.freeze
3
3
  end
data/lib/chewy.rb CHANGED
@@ -48,7 +48,8 @@ require 'chewy/index'
48
48
  require 'chewy/fields/base'
49
49
  require 'chewy/fields/root'
50
50
  require 'chewy/journal'
51
- require 'chewy/railtie' if defined?(::Rails::Railtie)
51
+ require 'chewy/railtie' if defined?(Rails::Railtie)
52
+ require 'chewy/elastic_client'
52
53
 
53
54
  ActiveSupport.on_load(:active_record) do
54
55
  include Chewy::Index::Observe::ActiveRecordMethods
@@ -97,12 +98,7 @@ module Chewy
97
98
  # Main elasticsearch-ruby client instance
98
99
  #
99
100
  def client
100
- Chewy.current[:chewy_client] ||= begin
101
- client_configuration = configuration.deep_dup
102
- client_configuration.delete(:prefix) # used by Chewy, not relevant to Elasticsearch::Client
103
- block = client_configuration[:transport_options].try(:delete, :proc)
104
- ::Elasticsearch::Client.new(client_configuration, &block)
105
- end
101
+ Chewy.current[:chewy_client] ||= Chewy::ElasticClient.new
106
102
  end
107
103
 
108
104
  # Sends wait_for_status request to ElasticSearch with status