chewy 7.2.4 → 7.2.5
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 +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
|