chewy 7.2.4 → 7.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +17 -0
- data/lib/chewy/config.rb +1 -1
- data/lib/chewy/index/observe/active_record_methods.rb +87 -0
- data/lib/chewy/index/observe/callback.rb +34 -0
- data/lib/chewy/index/observe.rb +3 -58
- data/lib/chewy/rspec/update_index.rb +10 -3
- data/lib/chewy/search.rb +1 -0
- data/lib/chewy/strategy/atomic_no_refresh.rb +18 -0
- data/lib/chewy/strategy/base.rb +10 -0
- data/lib/chewy/strategy/lazy_sidekiq.rb +64 -0
- data/lib/chewy/strategy.rb +2 -0
- data/lib/chewy/version.rb +1 -1
- data/lib/chewy.rb +1 -1
- data/migration_guide.md +1 -1
- data/spec/chewy/index/observe/active_record_methods_spec.rb +68 -0
- data/spec/chewy/index/observe/callback_spec.rb +139 -0
- data/spec/chewy/index/observe_spec.rb +27 -0
- data/spec/chewy/search_spec.rb +9 -0
- data/spec/chewy/strategy/atomic_no_refresh_spec.rb +60 -0
- data/spec/chewy/strategy/lazy_sidekiq_spec.rb +214 -0
- metadata +18 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37685481eff7312e08ba8d113f030ee5ab38e3414788c6cd2a0385829c99a712
|
4
|
+
data.tar.gz: d4a2a9d86d93e9a9c6ec5d11cabe51f67511f6b347faee3be9e276cf528c4dc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c973f623b179e98284019a2b2dddc1cb7506719585064673cccab0e1c790f599dce43a1395e364d5ed8be814ee0af1fe4985e188f25dcaa32e75eefa57a4f6e3
|
7
|
+
data.tar.gz: bd1c55232fd02520382a20109899f3b4d59a174c1d1ff875592f08582b5f3072dd7d6f47760df3be58f38756718f31f802832476a1e0c64ebfb9909748e31eac
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,18 @@
|
|
8
8
|
|
9
9
|
### Bugs Fixed
|
10
10
|
|
11
|
+
## 7.2.5 (2022-03-04)
|
12
|
+
|
13
|
+
### New Features
|
14
|
+
|
15
|
+
* [#827](https://github.com/toptal/chewy/pull/827): Add `:lazy_sidekiq` strategy, that defers not only importing but also `update_index` callback evaluation for created and updated objects. ([@sl4vr][])
|
16
|
+
* [#827](https://github.com/toptal/chewy/pull/827): Add `:atomic_no_refresh` strategy. Like `:atomic`, but `refresh=false` parameter is set. ([@barthez][])
|
17
|
+
* [#827](https://github.com/toptal/chewy/pull/827): Add `:no_refresh` chain call to `update_index` matcher to ensure import was called with `refresh=false`. ([@barthez][])
|
18
|
+
|
19
|
+
### Bugs Fixed
|
20
|
+
|
21
|
+
* [#835](https://github.com/toptal/chewy/pull/835): Support keyword arguments in named scopes. ([@milk1000cc][])
|
22
|
+
|
11
23
|
## 7.2.4 (2022-02-03)
|
12
24
|
|
13
25
|
### New Features
|
data/README.md
CHANGED
@@ -754,6 +754,23 @@ The default queue name is `chewy`, you can customize it in settings: `sidekiq.qu
|
|
754
754
|
Chewy.settings[:sidekiq] = {queue: :low}
|
755
755
|
```
|
756
756
|
|
757
|
+
#### `:lazy_sidekiq`
|
758
|
+
|
759
|
+
This does the same thing as `:sidekiq`, but with lazy evaluation. Beware it does not allow you to use any non-persistent record state for indices and conditions because record will be re-fetched from database asynchronously using sidekiq. However for destroying records strategy will fallback to `:sidekiq` because it's not possible to re-fetch deleted records from database.
|
760
|
+
|
761
|
+
The purpose of this strategy is to improve the response time of the code that should update indexes, as it does not only defer actual ES calls to a background job but `update_index` callbacks evaluation (for created and updated objects) too. Similar to `:sidekiq`, index update is asynchronous so this strategy cannot be used when data and index synchronization is required.
|
762
|
+
|
763
|
+
```ruby
|
764
|
+
Chewy.strategy(:lazy_sidekiq) do
|
765
|
+
City.popular.map(&:do_some_update_action!)
|
766
|
+
end
|
767
|
+
```
|
768
|
+
|
769
|
+
The default queue name is `chewy`, you can customize it in settings: `sidekiq.queue_name`
|
770
|
+
```
|
771
|
+
Chewy.settings[:sidekiq] = {queue: :low}
|
772
|
+
```
|
773
|
+
|
757
774
|
#### `:active_job`
|
758
775
|
|
759
776
|
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.
|
data/lib/chewy/config.rb
CHANGED
@@ -32,7 +32,7 @@ module Chewy
|
|
32
32
|
# Set number_of_replicas to 0 before reset and put the original value after
|
33
33
|
# https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html
|
34
34
|
:reset_no_replicas,
|
35
|
-
# Refresh or not when import async (sidekiq, activejob)
|
35
|
+
# Refresh or not when import async (sidekiq, lazy_sidekiq, activejob)
|
36
36
|
:disable_refresh_async,
|
37
37
|
# Default options for root of Chewy type. Allows to set default options
|
38
38
|
# for type mappings like `_all`.
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Index
|
3
|
+
module Observe
|
4
|
+
module Helpers
|
5
|
+
def update_proc(index_name, *args, &block)
|
6
|
+
options = args.extract_options!
|
7
|
+
method = args.first
|
8
|
+
|
9
|
+
proc do
|
10
|
+
reference = if index_name.is_a?(Proc)
|
11
|
+
if index_name.arity.zero?
|
12
|
+
instance_exec(&index_name)
|
13
|
+
else
|
14
|
+
index_name.call(self)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
index_name
|
18
|
+
end
|
19
|
+
|
20
|
+
index = Chewy.derive_name(reference)
|
21
|
+
|
22
|
+
next if Chewy.strategy.current.name == :bypass
|
23
|
+
|
24
|
+
backreference = if method && method.to_s == 'self'
|
25
|
+
self
|
26
|
+
elsif method
|
27
|
+
send(method)
|
28
|
+
else
|
29
|
+
instance_eval(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
index.update_index(backreference, options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def extract_callback_options!(args)
|
37
|
+
options = args.extract_options!
|
38
|
+
result = options.each_key.with_object({}) do |key, hash|
|
39
|
+
hash[key] = options.delete(key) if %i[if unless].include?(key)
|
40
|
+
end
|
41
|
+
args.push(options) unless options.empty?
|
42
|
+
result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
extend Helpers
|
47
|
+
|
48
|
+
module ActiveRecordMethods
|
49
|
+
extend ActiveSupport::Concern
|
50
|
+
|
51
|
+
def run_chewy_callbacks
|
52
|
+
chewy_callbacks.each { |callback| callback.call(self) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_chewy_indices
|
56
|
+
Chewy.strategy.current.update_chewy_indices(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
included do
|
60
|
+
class_attribute :chewy_callbacks, default: []
|
61
|
+
end
|
62
|
+
|
63
|
+
class_methods do
|
64
|
+
def initialize_chewy_callbacks
|
65
|
+
if Chewy.use_after_commit_callbacks
|
66
|
+
after_commit :update_chewy_indices, on: %i[create update]
|
67
|
+
after_commit :run_chewy_callbacks, on: :destroy
|
68
|
+
else
|
69
|
+
after_save :update_chewy_indices
|
70
|
+
after_destroy :run_chewy_callbacks
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
ruby2_keywords def update_index(type_name, *args, &block)
|
75
|
+
callback_options = Observe.extract_callback_options!(args)
|
76
|
+
update_proc = Observe.update_proc(type_name, *args, &block)
|
77
|
+
callback = Chewy::Index::Observe::Callback.new(update_proc, callback_options)
|
78
|
+
|
79
|
+
initialize_chewy_callbacks if chewy_callbacks.empty?
|
80
|
+
|
81
|
+
self.chewy_callbacks = chewy_callbacks.dup << callback
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Index
|
3
|
+
module Observe
|
4
|
+
class Callback
|
5
|
+
def initialize(executable, filters = {})
|
6
|
+
@executable = executable
|
7
|
+
@if_filter = filters[:if]
|
8
|
+
@unless_filter = filters[:unless]
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(context)
|
12
|
+
return if !@if_filter.nil? && !eval_filter(@if_filter, context)
|
13
|
+
return if !@unless_filter.nil? && eval_filter(@unless_filter, context)
|
14
|
+
|
15
|
+
eval_proc(@executable, context)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def eval_filter(filter, context)
|
21
|
+
case filter
|
22
|
+
when Symbol then context.send(filter)
|
23
|
+
when Proc then eval_proc(filter, context)
|
24
|
+
else filter
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def eval_proc(executable, context)
|
29
|
+
executable.arity.zero? ? context.instance_exec(&executable) : executable.call(context)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/chewy/index/observe.rb
CHANGED
@@ -1,66 +1,11 @@
|
|
1
|
+
require 'chewy/index/observe/callback'
|
2
|
+
require 'chewy/index/observe/active_record_methods'
|
3
|
+
|
1
4
|
module Chewy
|
2
5
|
class Index
|
3
6
|
module Observe
|
4
7
|
extend ActiveSupport::Concern
|
5
8
|
|
6
|
-
module Helpers
|
7
|
-
def update_proc(index_name, *args, &block)
|
8
|
-
options = args.extract_options!
|
9
|
-
method = args.first
|
10
|
-
|
11
|
-
proc do
|
12
|
-
reference = if index_name.is_a?(Proc)
|
13
|
-
if index_name.arity.zero?
|
14
|
-
instance_exec(&index_name)
|
15
|
-
else
|
16
|
-
index_name.call(self)
|
17
|
-
end
|
18
|
-
else
|
19
|
-
index_name
|
20
|
-
end
|
21
|
-
|
22
|
-
index = Chewy.derive_name(reference)
|
23
|
-
|
24
|
-
next if Chewy.strategy.current.name == :bypass
|
25
|
-
|
26
|
-
backreference = if method && method.to_s == 'self'
|
27
|
-
self
|
28
|
-
elsif method
|
29
|
-
send(method)
|
30
|
-
else
|
31
|
-
instance_eval(&block)
|
32
|
-
end
|
33
|
-
|
34
|
-
index.update_index(backreference, options)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def extract_callback_options!(args)
|
39
|
-
options = args.extract_options!
|
40
|
-
result = options.each_key.with_object({}) do |key, hash|
|
41
|
-
hash[key] = options.delete(key) if %i[if unless].include?(key)
|
42
|
-
end
|
43
|
-
args.push(options) unless options.empty?
|
44
|
-
result
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
extend Helpers
|
49
|
-
|
50
|
-
module ActiveRecordMethods
|
51
|
-
ruby2_keywords def update_index(type_name, *args, &block)
|
52
|
-
callback_options = Observe.extract_callback_options!(args)
|
53
|
-
update_proc = Observe.update_proc(type_name, *args, &block)
|
54
|
-
|
55
|
-
if Chewy.use_after_commit_callbacks
|
56
|
-
after_commit(**callback_options, &update_proc)
|
57
|
-
else
|
58
|
-
after_save(**callback_options, &update_proc)
|
59
|
-
after_destroy(**callback_options, &update_proc)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
9
|
module ClassMethods
|
65
10
|
def update_index(objects, options = {})
|
66
11
|
Chewy.strategy.current.update(self, objects, options)
|
@@ -88,6 +88,11 @@ RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:dis
|
|
88
88
|
@only = true
|
89
89
|
end
|
90
90
|
|
91
|
+
# Expect import to be called with refresh=false parameter
|
92
|
+
chain(:no_refresh) do
|
93
|
+
@no_refresh = true
|
94
|
+
end
|
95
|
+
|
91
96
|
def supports_block_expectations?
|
92
97
|
true
|
93
98
|
end
|
@@ -100,11 +105,13 @@ RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:dis
|
|
100
105
|
|
101
106
|
index = Chewy.derive_name(index_name)
|
102
107
|
if defined?(Mocha) && RSpec.configuration.mock_framework.to_s == 'RSpec::Core::MockingAdapters::Mocha'
|
103
|
-
|
108
|
+
params_matcher = @no_refresh ? has_entry(refresh: false) : any_parameters
|
109
|
+
Chewy::Index::Import::BulkRequest.stubs(:new).with(index, params_matcher).returns(mock_bulk_request)
|
104
110
|
else
|
105
111
|
mocked_already = ::RSpec::Mocks.space.proxy_for(Chewy::Index::Import::BulkRequest).method_double_if_exists_for_message(:new)
|
106
112
|
allow(Chewy::Index::Import::BulkRequest).to receive(:new).and_call_original unless mocked_already
|
107
|
-
|
113
|
+
params_matcher = @no_refresh ? hash_including(refresh: false) : any_args
|
114
|
+
allow(Chewy::Index::Import::BulkRequest).to receive(:new).with(index, params_matcher).and_return(mock_bulk_request)
|
108
115
|
end
|
109
116
|
|
110
117
|
Chewy.strategy(options[:strategy] || :atomic) { block.call }
|
@@ -146,7 +153,7 @@ RSpec::Matchers.define :update_index do |index_name, options = {}| # rubocop:dis
|
|
146
153
|
output = ''
|
147
154
|
|
148
155
|
if mock_bulk_request.updates.none?
|
149
|
-
output << "Expected index `#{index_name}` to be updated, but it was not\n"
|
156
|
+
output << "Expected index `#{index_name}` to be updated#{' with no refresh' if @no_refresh}, but it was not\n"
|
150
157
|
elsif @missed_reindex.present? || @missed_delete.present?
|
151
158
|
message = "Expected index `#{index_name}` "
|
152
159
|
message << [
|
data/lib/chewy/search.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Strategy
|
3
|
+
# This strategy works like atomic but import objects with `refresh=false` parameter.
|
4
|
+
#
|
5
|
+
# Chewy.strategy(:atomic_no_refresh) do
|
6
|
+
# User.all.map(&:save) # Does nothing here
|
7
|
+
# Post.all.map(&:save) # And here
|
8
|
+
# # It imports all the changed users and posts right here
|
9
|
+
# # before block leaving with bulk ES API, kinda optimization
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
class AtomicNoRefresh < Atomic
|
13
|
+
def leave
|
14
|
+
@stash.all? { |type, ids| type.import!(ids, refresh: false) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/chewy/strategy/base.rb
CHANGED
@@ -22,6 +22,16 @@ module Chewy
|
|
22
22
|
# strategies stack
|
23
23
|
#
|
24
24
|
def leave; end
|
25
|
+
|
26
|
+
# This method called when some model record is created or updated.
|
27
|
+
# Normally it will just evaluate all the Chewy callbacks and pass results
|
28
|
+
# to current strategy's update method.
|
29
|
+
# However it's possible to override it to achieve delayed evaluation of
|
30
|
+
# callbacks, e.g. using sidekiq.
|
31
|
+
#
|
32
|
+
def update_chewy_indices(object)
|
33
|
+
object.run_chewy_callbacks
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Strategy
|
3
|
+
# The strategy works the same way as sidekiq, but performs
|
4
|
+
# async evaluation of all index callbacks on model create and update
|
5
|
+
# driven by sidekiq
|
6
|
+
#
|
7
|
+
# Chewy.strategy(:lazy_sidekiq) do
|
8
|
+
# User.all.map(&:save) # Does nothing here
|
9
|
+
# Post.all.map(&:save) # And here
|
10
|
+
# # It schedules import of all the changed users and posts right here
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
class LazySidekiq < Sidekiq
|
14
|
+
class IndicesUpdateWorker
|
15
|
+
include ::Sidekiq::Worker
|
16
|
+
|
17
|
+
def perform(models)
|
18
|
+
Chewy.strategy(strategy) do
|
19
|
+
models.each do |model_type, model_ids|
|
20
|
+
model_type.constantize.where(id: model_ids).each(&:run_chewy_callbacks)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def strategy
|
28
|
+
Chewy.disable_refresh_async ? :atomic_no_refresh : :atomic
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
# Use parent's @stash to store destroyed records, since callbacks for them have to
|
34
|
+
# be run immediately on the strategy block end because we won't be able to fetch
|
35
|
+
# records further in IndicesUpdateWorker. This will be done by avoiding of
|
36
|
+
# LazySidekiq#update_chewy_indices call and calling LazySidekiq#update instead.
|
37
|
+
super
|
38
|
+
|
39
|
+
# @lazy_stash is used to store all the lazy evaluated callbacks with call of
|
40
|
+
# strategy's #update_chewy_indices.
|
41
|
+
@lazy_stash = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def leave
|
45
|
+
# Fallback to Sidekiq#leave implementation for destroyed records stored in @stash.
|
46
|
+
super
|
47
|
+
|
48
|
+
# Proceed with other records stored in @lazy_stash
|
49
|
+
return if @lazy_stash.empty?
|
50
|
+
|
51
|
+
::Sidekiq::Client.push(
|
52
|
+
'queue' => sidekiq_queue,
|
53
|
+
'class' => Chewy::Strategy::LazySidekiq::IndicesUpdateWorker,
|
54
|
+
'args' => [@lazy_stash]
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def update_chewy_indices(object)
|
59
|
+
@lazy_stash[object.class.name] ||= []
|
60
|
+
@lazy_stash[object.class.name] |= Array.wrap(object.id)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/chewy/strategy.rb
CHANGED
@@ -2,10 +2,12 @@ require 'chewy/strategy/base'
|
|
2
2
|
require 'chewy/strategy/bypass'
|
3
3
|
require 'chewy/strategy/urgent'
|
4
4
|
require 'chewy/strategy/atomic'
|
5
|
+
require 'chewy/strategy/atomic_no_refresh'
|
5
6
|
|
6
7
|
begin
|
7
8
|
require 'sidekiq'
|
8
9
|
require 'chewy/strategy/sidekiq'
|
10
|
+
require 'chewy/strategy/lazy_sidekiq'
|
9
11
|
rescue LoadError
|
10
12
|
nil
|
11
13
|
end
|
data/lib/chewy/version.rb
CHANGED
data/lib/chewy.rb
CHANGED
@@ -50,7 +50,7 @@ require 'chewy/journal'
|
|
50
50
|
require 'chewy/railtie' if defined?(::Rails::Railtie)
|
51
51
|
|
52
52
|
ActiveSupport.on_load(:active_record) do
|
53
|
-
|
53
|
+
include Chewy::Index::Observe::ActiveRecordMethods
|
54
54
|
end
|
55
55
|
|
56
56
|
module Chewy
|
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/
|
12
|
+
* Study carefully [Breaking changes in 7.0](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/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
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Chewy::Index::Observe::ActiveRecordMethods do
|
4
|
+
describe '.update_index' do
|
5
|
+
before { stub_model(:city) }
|
6
|
+
|
7
|
+
it 'initializes chewy callbacks when first update_index is evaluated' do
|
8
|
+
expect(City).to receive(:initialize_chewy_callbacks).once
|
9
|
+
City.update_index 'cities', :self
|
10
|
+
City.update_index 'countries', -> {}
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'adds chewy callbacks to model' do
|
14
|
+
expect(City.chewy_callbacks.count).to eq(0)
|
15
|
+
|
16
|
+
City.update_index 'cities', :self
|
17
|
+
City.update_index 'countries', -> {}
|
18
|
+
|
19
|
+
expect(City.chewy_callbacks.count).to eq(2)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'callbacks' do
|
24
|
+
before { stub_model(:city) { update_index 'cities', :self } }
|
25
|
+
before { stub_index(:cities) { index_scope City } }
|
26
|
+
before { allow(Chewy).to receive(:use_after_commit_callbacks).and_return(use_after_commit_callbacks) }
|
27
|
+
|
28
|
+
let(:city) do
|
29
|
+
Chewy.strategy(:bypass) do
|
30
|
+
City.create!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
shared_examples 'handles callbacks correctly' do
|
35
|
+
it 'handles callbacks with strategy for possible lazy evaluation on save!' do
|
36
|
+
Chewy.strategy(:urgent) do
|
37
|
+
expect(city).to receive(:update_chewy_indices).and_call_original
|
38
|
+
expect(Chewy.strategy.current).to receive(:update_chewy_indices).with(city)
|
39
|
+
expect(city).not_to receive(:run_chewy_callbacks)
|
40
|
+
|
41
|
+
city.save!
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'runs callbacks at the moment on destroy' do
|
46
|
+
Chewy.strategy(:urgent) do
|
47
|
+
expect(city).not_to receive(:update_chewy_indices)
|
48
|
+
expect(Chewy.strategy.current).not_to receive(:update_chewy_indices)
|
49
|
+
expect(city).to receive(:run_chewy_callbacks)
|
50
|
+
|
51
|
+
city.destroy
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when Chewy.use_after_commit_callbacks is true' do
|
57
|
+
let(:use_after_commit_callbacks) { true }
|
58
|
+
|
59
|
+
include_examples 'handles callbacks correctly'
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when Chewy.use_after_commit_callbacks is false' do
|
63
|
+
let(:use_after_commit_callbacks) { false }
|
64
|
+
|
65
|
+
include_examples 'handles callbacks correctly'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Chewy::Index::Observe::Callback do
|
4
|
+
subject(:callback) { described_class.new(executable) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
stub_model(:city) do
|
8
|
+
attr_accessor :population
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:city) { City.create!(population: 100) }
|
13
|
+
|
14
|
+
describe '#call' do
|
15
|
+
context 'when executable is has arity 0' do
|
16
|
+
let(:executable) { -> { population } }
|
17
|
+
|
18
|
+
it 'calls exectuable within context' do
|
19
|
+
expect(callback.call(city)).to eq(city.population)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when executable is has arity 1' do
|
24
|
+
let(:executable) { ->(record) { record.population } }
|
25
|
+
|
26
|
+
it 'calls exectuable within context' do
|
27
|
+
expect(callback.call(city)).to eq(city.population)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'filters' do
|
32
|
+
let(:executable) { ->(_) {} }
|
33
|
+
|
34
|
+
describe 'if' do
|
35
|
+
subject(:callback) { described_class.new(executable, if: filter) }
|
36
|
+
|
37
|
+
shared_examples 'an if filter' do
|
38
|
+
context 'when condition is true' do
|
39
|
+
let(:condition) { true }
|
40
|
+
|
41
|
+
specify do
|
42
|
+
expect(executable).to receive(:call).with(city)
|
43
|
+
|
44
|
+
callback.call(city)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when condition is false' do
|
49
|
+
let(:condition) { false }
|
50
|
+
|
51
|
+
specify do
|
52
|
+
expect(executable).not_to receive(:call)
|
53
|
+
|
54
|
+
callback.call(city)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when filter is symbol' do
|
60
|
+
let(:filter) { :condition }
|
61
|
+
|
62
|
+
before do
|
63
|
+
allow(city).to receive(:condition).and_return(condition)
|
64
|
+
end
|
65
|
+
|
66
|
+
include_examples 'an if filter'
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when filter is proc' do
|
70
|
+
let(:filter) { -> { condition_state } }
|
71
|
+
|
72
|
+
before do
|
73
|
+
allow_any_instance_of(City).to receive(:condition_state).and_return(condition)
|
74
|
+
end
|
75
|
+
|
76
|
+
include_examples 'an if filter'
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when filter is literal' do
|
80
|
+
let(:filter) { condition }
|
81
|
+
|
82
|
+
include_examples 'an if filter'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'unless' do
|
87
|
+
subject(:callback) { described_class.new(executable, unless: filter) }
|
88
|
+
|
89
|
+
shared_examples 'an unless filter' do
|
90
|
+
context 'when condition is true' do
|
91
|
+
let(:condition) { true }
|
92
|
+
|
93
|
+
specify do
|
94
|
+
expect(executable).not_to receive(:call)
|
95
|
+
|
96
|
+
callback.call(city)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when condition is false' do
|
101
|
+
let(:condition) { false }
|
102
|
+
|
103
|
+
specify do
|
104
|
+
expect(executable).to receive(:call).with(city)
|
105
|
+
|
106
|
+
callback.call(city)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when filter is symbol' do
|
112
|
+
let(:filter) { :condition }
|
113
|
+
|
114
|
+
before do
|
115
|
+
allow(city).to receive(:condition).and_return(condition)
|
116
|
+
end
|
117
|
+
|
118
|
+
include_examples 'an unless filter'
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when filter is proc' do
|
122
|
+
let(:filter) { -> { condition_state } }
|
123
|
+
|
124
|
+
before do
|
125
|
+
allow_any_instance_of(City).to receive(:condition_state).and_return(condition)
|
126
|
+
end
|
127
|
+
|
128
|
+
include_examples 'an unless filter'
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'when filter is literal' do
|
132
|
+
let(:filter) { condition }
|
133
|
+
|
134
|
+
include_examples 'an unless filter'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -57,6 +57,9 @@ describe Chewy::Index::Observe do
|
|
57
57
|
specify { expect { city.save! }.to update_index('cities').and_reindex(city).only }
|
58
58
|
specify { expect { city.save! }.to update_index('countries').and_reindex(country1).only }
|
59
59
|
|
60
|
+
specify { expect { city.destroy }.to update_index('cities') }
|
61
|
+
specify { expect { city.destroy }.to update_index('countries').and_reindex(country1).only }
|
62
|
+
|
60
63
|
specify { expect { city.update!(country: nil) }.to update_index('cities').and_reindex(city).only }
|
61
64
|
specify { expect { city.update!(country: nil) }.to update_index('countries').and_reindex(country1).only }
|
62
65
|
|
@@ -78,9 +81,13 @@ describe Chewy::Index::Observe do
|
|
78
81
|
specify { expect { country.save! }.to update_index('cities').and_reindex(country.cities).only }
|
79
82
|
specify { expect { country.save! }.to update_index('countries').and_reindex(country).only }
|
80
83
|
|
84
|
+
specify { expect { country.destroy }.to update_index('cities').and_reindex(country.cities).only }
|
85
|
+
specify { expect { country.destroy }.to update_index('countries') }
|
86
|
+
|
81
87
|
context 'conditional update' do
|
82
88
|
let(:update_condition) { false }
|
83
89
|
specify { expect { country.save! }.not_to update_index('cities') }
|
90
|
+
specify { expect { country.destroy }.not_to update_index('cities') }
|
84
91
|
end
|
85
92
|
end
|
86
93
|
end
|
@@ -97,6 +104,16 @@ describe Chewy::Index::Observe do
|
|
97
104
|
end
|
98
105
|
end
|
99
106
|
end
|
107
|
+
|
108
|
+
specify do
|
109
|
+
city = Chewy.strategy(:bypass) { City.create! }
|
110
|
+
|
111
|
+
Chewy.strategy(:urgent) do
|
112
|
+
ActiveRecord::Base.transaction do
|
113
|
+
expect { city.destroy }.not_to update_index('cities')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
100
117
|
end
|
101
118
|
|
102
119
|
context do
|
@@ -111,6 +128,16 @@ describe Chewy::Index::Observe do
|
|
111
128
|
end
|
112
129
|
end
|
113
130
|
end
|
131
|
+
|
132
|
+
specify do
|
133
|
+
city = Chewy.strategy(:bypass) { City.create! }
|
134
|
+
|
135
|
+
Chewy.strategy(:urgent) do
|
136
|
+
ActiveRecord::Base.transaction do
|
137
|
+
expect { city.destroy }.to update_index('cities')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
114
141
|
end
|
115
142
|
end
|
116
143
|
end
|
data/spec/chewy/search_spec.rb
CHANGED
@@ -48,6 +48,10 @@ describe Chewy::Search do
|
|
48
48
|
filter { match name: "Name#{index}" }
|
49
49
|
end
|
50
50
|
|
51
|
+
def self.by_rating_with_kwargs(value, options:) # rubocop:disable Lint/UnusedMethodArgument
|
52
|
+
filter { match rating: value }
|
53
|
+
end
|
54
|
+
|
51
55
|
index_scope City
|
52
56
|
field :name, type: 'keyword'
|
53
57
|
field :rating, type: :integer
|
@@ -114,5 +118,10 @@ describe Chewy::Search do
|
|
114
118
|
specify { expect(CountriesIndex.by_rating(3).by_name(5).map(&:class)).to eq([CountriesIndex]) }
|
115
119
|
specify { expect(CountriesIndex.order(:name).by_rating(3).map(&:rating)).to eq([3]) }
|
116
120
|
specify { expect(CountriesIndex.order(:name).by_rating(3).map(&:class)).to eq([CountriesIndex]) }
|
121
|
+
|
122
|
+
specify 'supports keyword arguments' do
|
123
|
+
expect(CitiesIndex.by_rating_with_kwargs(3, options: 'blah blah blah').map(&:rating)).to eq([3])
|
124
|
+
expect(CitiesIndex.order(:name).by_rating_with_kwargs(3, options: 'blah blah blah').map(&:rating)).to eq([3])
|
125
|
+
end
|
117
126
|
end
|
118
127
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Chewy::Strategy::AtomicNoRefresh, :orm do
|
4
|
+
around { |example| Chewy.strategy(:bypass) { example.run } }
|
5
|
+
|
6
|
+
before do
|
7
|
+
stub_model(:country) do
|
8
|
+
update_index('countries') { self }
|
9
|
+
end
|
10
|
+
|
11
|
+
stub_index(:countries) do
|
12
|
+
index_scope Country
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:country) { Country.create!(name: 'hello', country_code: 'HL') }
|
17
|
+
let(:other_country) { Country.create!(name: 'world', country_code: 'WD') }
|
18
|
+
|
19
|
+
specify do
|
20
|
+
expect { [country, other_country].map(&:save!) }
|
21
|
+
.to update_index(CountriesIndex, strategy: :atomic_no_refresh)
|
22
|
+
.and_reindex(country, other_country).only.no_refresh
|
23
|
+
end
|
24
|
+
|
25
|
+
specify do
|
26
|
+
expect { [country, other_country].map(&:destroy) }
|
27
|
+
.to update_index(CountriesIndex, strategy: :atomic_no_refresh)
|
28
|
+
.and_delete(country, other_country).only.no_refresh
|
29
|
+
end
|
30
|
+
|
31
|
+
context do
|
32
|
+
before do
|
33
|
+
stub_index(:countries) do
|
34
|
+
index_scope Country
|
35
|
+
root id: -> { country_code }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
specify do
|
40
|
+
expect { [country, other_country].map(&:save!) }
|
41
|
+
.to update_index(CountriesIndex, strategy: :atomic_no_refresh)
|
42
|
+
.and_reindex('HL', 'WD').only.no_refresh
|
43
|
+
end
|
44
|
+
|
45
|
+
specify do
|
46
|
+
expect { [country, other_country].map(&:destroy) }
|
47
|
+
.to update_index(CountriesIndex, strategy: :atomic_no_refresh)
|
48
|
+
.and_delete('HL', 'WD').only.no_refresh
|
49
|
+
end
|
50
|
+
|
51
|
+
specify do
|
52
|
+
expect do
|
53
|
+
country.save!
|
54
|
+
other_country.destroy
|
55
|
+
end
|
56
|
+
.to update_index(CountriesIndex, strategy: :atomic_no_refresh)
|
57
|
+
.and_reindex('HL').and_delete('WD').only.no_refresh
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if defined?(::Sidekiq)
|
4
|
+
require 'sidekiq/testing'
|
5
|
+
|
6
|
+
describe Chewy::Strategy::LazySidekiq do
|
7
|
+
around do |example|
|
8
|
+
sidekiq_settings = Chewy.settings[:sidekiq]
|
9
|
+
Chewy.settings[:sidekiq] = {queue: 'low'}
|
10
|
+
Chewy.strategy(:bypass) { example.run }
|
11
|
+
Chewy.settings[:sidekiq] = sidekiq_settings
|
12
|
+
end
|
13
|
+
before { ::Sidekiq::Worker.clear_all }
|
14
|
+
|
15
|
+
context 'strategy' do
|
16
|
+
before do
|
17
|
+
stub_model(:city) do
|
18
|
+
update_index('cities') { self }
|
19
|
+
end
|
20
|
+
|
21
|
+
stub_index(:cities) do
|
22
|
+
index_scope City
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:city) { City.create!(name: 'hello') }
|
27
|
+
let(:other_city) { City.create!(name: 'world') }
|
28
|
+
|
29
|
+
it 'does not update indices synchronously' do
|
30
|
+
expect { [city, other_city].map(&:save!) }
|
31
|
+
.not_to update_index(CitiesIndex, strategy: :lazy_sidekiq)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'updates indices asynchronously on record save' do
|
35
|
+
expect(::Sidekiq::Client).to receive(:push)
|
36
|
+
.with(hash_including(
|
37
|
+
'class' => Chewy::Strategy::LazySidekiq::IndicesUpdateWorker,
|
38
|
+
'queue' => 'low'
|
39
|
+
))
|
40
|
+
.and_call_original
|
41
|
+
.once
|
42
|
+
::Sidekiq::Testing.inline! do
|
43
|
+
expect { [city, other_city].map(&:save!) }
|
44
|
+
.to update_index(CitiesIndex, strategy: :lazy_sidekiq)
|
45
|
+
.and_reindex(city, other_city).only
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'updates indices asynchronously with falling back to sidekiq strategy on record destroy' do
|
50
|
+
expect(::Sidekiq::Client).not_to receive(:push)
|
51
|
+
.with(hash_including(
|
52
|
+
'class' => Chewy::Strategy::LazySidekiq::IndicesUpdateWorker,
|
53
|
+
'queue' => 'low'
|
54
|
+
))
|
55
|
+
expect(::Sidekiq::Client).to receive(:push)
|
56
|
+
.with(hash_including(
|
57
|
+
'class' => Chewy::Strategy::Sidekiq::Worker,
|
58
|
+
'queue' => 'low',
|
59
|
+
'args' => ['CitiesIndex', [city.id, other_city.id]]
|
60
|
+
))
|
61
|
+
.and_call_original
|
62
|
+
.once
|
63
|
+
::Sidekiq::Testing.inline! do
|
64
|
+
expect { [city, other_city].map(&:destroy) }.to update_index(CitiesIndex, strategy: :sidekiq)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'calls Index#import!' do
|
69
|
+
allow(City).to receive(:where).with(id: [city.id, other_city.id]).and_return([city, other_city])
|
70
|
+
expect(city).to receive(:run_chewy_callbacks).and_call_original
|
71
|
+
expect(other_city).to receive(:run_chewy_callbacks).and_call_original
|
72
|
+
|
73
|
+
expect do
|
74
|
+
::Sidekiq::Testing.inline! do
|
75
|
+
Chewy::Strategy::LazySidekiq::IndicesUpdateWorker.new.perform({'City' => [city.id, other_city.id]})
|
76
|
+
end
|
77
|
+
end.to update_index(CitiesIndex).and_reindex(city, other_city).only
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when Chewy.disable_refresh_async is true' do
|
81
|
+
before do
|
82
|
+
allow(Chewy).to receive(:disable_refresh_async).and_return(true)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'calls Index#import! with refresh false' do
|
86
|
+
allow(City).to receive(:where).with(id: [city.id, other_city.id]).and_return([city, other_city])
|
87
|
+
expect(city).to receive(:run_chewy_callbacks).and_call_original
|
88
|
+
expect(other_city).to receive(:run_chewy_callbacks).and_call_original
|
89
|
+
|
90
|
+
expect do
|
91
|
+
::Sidekiq::Testing.inline! do
|
92
|
+
Chewy::Strategy::LazySidekiq::IndicesUpdateWorker.new.perform({'City' => [city.id, other_city.id]})
|
93
|
+
end
|
94
|
+
end.to update_index(CitiesIndex).and_reindex(city, other_city).only.no_refresh
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'integration' do
|
100
|
+
around { |example| ::Sidekiq::Testing.inline! { example.run } }
|
101
|
+
|
102
|
+
let(:update_condition) { true }
|
103
|
+
|
104
|
+
before do
|
105
|
+
city_model
|
106
|
+
country_model
|
107
|
+
|
108
|
+
City.belongs_to :country
|
109
|
+
Country.has_many :cities
|
110
|
+
|
111
|
+
stub_index(:cities) do
|
112
|
+
index_scope City
|
113
|
+
end
|
114
|
+
|
115
|
+
stub_index(:countries) do
|
116
|
+
index_scope Country
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'state dependent' do
|
121
|
+
let(:city_model) do
|
122
|
+
stub_model(:city) do
|
123
|
+
update_index(-> { 'cities' }, :self)
|
124
|
+
update_index('countries') { changes['country_id'] || previous_changes['country_id'] || country }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
let(:country_model) do
|
129
|
+
stub_model(:country) do
|
130
|
+
update_index('cities', if: -> { state_dependent_update_condition }) { cities }
|
131
|
+
update_index(-> { 'countries' }, :self)
|
132
|
+
attr_accessor :state_dependent_update_condition
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'city updates' do
|
137
|
+
let!(:country1) { Country.create!(id: 1) }
|
138
|
+
let!(:country2) { Country.create!(id: 2) }
|
139
|
+
let!(:city) { City.create!(id: 1, country: country1) }
|
140
|
+
|
141
|
+
it 'does not update index of removed entity because model state on the moment of save cannot be fetched' do
|
142
|
+
expect { city.update!(country: nil) }.not_to update_index('countries', strategy: :lazy_sidekiq)
|
143
|
+
end
|
144
|
+
it 'does not update index of removed entity because model state on the moment of save cannot be fetched' do
|
145
|
+
expect { city.update!(country: country2) }.to update_index('countries', strategy: :lazy_sidekiq).and_reindex(country2).only
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'country updates' do
|
150
|
+
let!(:country) do
|
151
|
+
cities = Array.new(2) { |i| City.create!(id: i) }
|
152
|
+
Country.create!(id: 1, cities: cities, state_dependent_update_condition: update_condition)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'does not update index because state of attribute cannot be fetched' do
|
156
|
+
expect { country.save! }.not_to update_index('cities', strategy: :lazy_sidekiq)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'state independent' do
|
162
|
+
let(:city_model) do
|
163
|
+
stub_model(:city) do
|
164
|
+
update_index(-> { 'cities' }, :self)
|
165
|
+
update_index('countries') { country }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
let(:country_model) do
|
170
|
+
stub_model(:country) do
|
171
|
+
update_index('cities', if: -> { state_independent_update_condition }) { cities }
|
172
|
+
update_index(-> { 'countries' }, :self)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
before do
|
177
|
+
allow_any_instance_of(Country).to receive(:state_independent_update_condition).and_return(update_condition)
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'when city updates' do
|
181
|
+
let!(:country1) { Country.create!(id: 1) }
|
182
|
+
let!(:country2) { Country.create!(id: 2) }
|
183
|
+
let!(:city) { City.create!(id: 1, country: country1) }
|
184
|
+
|
185
|
+
specify { expect { city.save! }.to update_index('cities', strategy: :lazy_sidekiq).and_reindex(city).only }
|
186
|
+
specify { expect { city.save! }.to update_index('countries', strategy: :lazy_sidekiq).and_reindex(country1).only }
|
187
|
+
|
188
|
+
specify { expect { city.destroy }.not_to update_index('cities').and_reindex(city).only }
|
189
|
+
specify { expect { city.destroy }.to update_index('countries', strategy: :sidekiq).and_reindex(country1).only }
|
190
|
+
|
191
|
+
specify { expect { city.update!(country: nil) }.to update_index('cities', strategy: :lazy_sidekiq).and_reindex(city).only }
|
192
|
+
specify { expect { city.update!(country: country2) }.to update_index('cities', strategy: :lazy_sidekiq).and_reindex(city).only }
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when country updates' do
|
196
|
+
let!(:country) do
|
197
|
+
cities = Array.new(2) { |i| City.create!(id: i) }
|
198
|
+
Country.create!(id: 1, cities: cities)
|
199
|
+
end
|
200
|
+
specify { expect { country.save! }.to update_index('cities', strategy: :lazy_sidekiq).and_reindex(country.cities).only }
|
201
|
+
specify { expect { country.save! }.to update_index('countries', strategy: :lazy_sidekiq).and_reindex(country).only }
|
202
|
+
|
203
|
+
specify { expect { country.destroy }.to update_index('cities', strategy: :sidekiq).and_reindex(country.cities).only }
|
204
|
+
specify { expect { country.destroy }.not_to update_index('countries').and_reindex(country).only }
|
205
|
+
|
206
|
+
context 'when update condition is false' do
|
207
|
+
let(:update_condition) { false }
|
208
|
+
specify { expect { country.save! }.not_to update_index('cities', strategy: :lazy_sidekiq) }
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chewy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.2.
|
4
|
+
version: 7.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toptal, LLC
|
8
8
|
- pyromaniac
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-03-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: database_cleaner
|
@@ -265,6 +265,8 @@ files:
|
|
265
265
|
- lib/chewy/index/import/routine.rb
|
266
266
|
- lib/chewy/index/mapping.rb
|
267
267
|
- lib/chewy/index/observe.rb
|
268
|
+
- lib/chewy/index/observe/active_record_methods.rb
|
269
|
+
- lib/chewy/index/observe/callback.rb
|
268
270
|
- lib/chewy/index/settings.rb
|
269
271
|
- lib/chewy/index/specification.rb
|
270
272
|
- lib/chewy/index/syncer.rb
|
@@ -337,8 +339,10 @@ files:
|
|
337
339
|
- lib/chewy/strategy.rb
|
338
340
|
- lib/chewy/strategy/active_job.rb
|
339
341
|
- lib/chewy/strategy/atomic.rb
|
342
|
+
- lib/chewy/strategy/atomic_no_refresh.rb
|
340
343
|
- lib/chewy/strategy/base.rb
|
341
344
|
- lib/chewy/strategy/bypass.rb
|
345
|
+
- lib/chewy/strategy/lazy_sidekiq.rb
|
342
346
|
- lib/chewy/strategy/sidekiq.rb
|
343
347
|
- lib/chewy/strategy/urgent.rb
|
344
348
|
- lib/chewy/version.rb
|
@@ -360,6 +364,8 @@ files:
|
|
360
364
|
- spec/chewy/index/import/routine_spec.rb
|
361
365
|
- spec/chewy/index/import_spec.rb
|
362
366
|
- spec/chewy/index/mapping_spec.rb
|
367
|
+
- spec/chewy/index/observe/active_record_methods_spec.rb
|
368
|
+
- spec/chewy/index/observe/callback_spec.rb
|
363
369
|
- spec/chewy/index/observe_spec.rb
|
364
370
|
- spec/chewy/index/settings_spec.rb
|
365
371
|
- spec/chewy/index/specification_spec.rb
|
@@ -426,7 +432,9 @@ files:
|
|
426
432
|
- spec/chewy/search_spec.rb
|
427
433
|
- spec/chewy/stash_spec.rb
|
428
434
|
- spec/chewy/strategy/active_job_spec.rb
|
435
|
+
- spec/chewy/strategy/atomic_no_refresh_spec.rb
|
429
436
|
- spec/chewy/strategy/atomic_spec.rb
|
437
|
+
- spec/chewy/strategy/lazy_sidekiq_spec.rb
|
430
438
|
- spec/chewy/strategy/sidekiq_spec.rb
|
431
439
|
- spec/chewy/strategy_spec.rb
|
432
440
|
- spec/chewy_spec.rb
|
@@ -438,7 +446,7 @@ homepage: https://github.com/toptal/chewy
|
|
438
446
|
licenses:
|
439
447
|
- MIT
|
440
448
|
metadata: {}
|
441
|
-
post_install_message:
|
449
|
+
post_install_message:
|
442
450
|
rdoc_options: []
|
443
451
|
require_paths:
|
444
452
|
- lib
|
@@ -453,8 +461,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
453
461
|
- !ruby/object:Gem::Version
|
454
462
|
version: '0'
|
455
463
|
requirements: []
|
456
|
-
rubygems_version: 3.
|
457
|
-
signing_key:
|
464
|
+
rubygems_version: 3.1.6
|
465
|
+
signing_key:
|
458
466
|
specification_version: 4
|
459
467
|
summary: Elasticsearch ODM client wrapper
|
460
468
|
test_files:
|
@@ -472,6 +480,8 @@ test_files:
|
|
472
480
|
- spec/chewy/index/import/routine_spec.rb
|
473
481
|
- spec/chewy/index/import_spec.rb
|
474
482
|
- spec/chewy/index/mapping_spec.rb
|
483
|
+
- spec/chewy/index/observe/active_record_methods_spec.rb
|
484
|
+
- spec/chewy/index/observe/callback_spec.rb
|
475
485
|
- spec/chewy/index/observe_spec.rb
|
476
486
|
- spec/chewy/index/settings_spec.rb
|
477
487
|
- spec/chewy/index/specification_spec.rb
|
@@ -538,7 +548,9 @@ test_files:
|
|
538
548
|
- spec/chewy/search_spec.rb
|
539
549
|
- spec/chewy/stash_spec.rb
|
540
550
|
- spec/chewy/strategy/active_job_spec.rb
|
551
|
+
- spec/chewy/strategy/atomic_no_refresh_spec.rb
|
541
552
|
- spec/chewy/strategy/atomic_spec.rb
|
553
|
+
- spec/chewy/strategy/lazy_sidekiq_spec.rb
|
542
554
|
- spec/chewy/strategy/sidekiq_spec.rb
|
543
555
|
- spec/chewy/strategy_spec.rb
|
544
556
|
- spec/chewy_spec.rb
|