chewy 7.5.1 → 8.0.0.pre.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/ruby.yml +17 -5
- data/CHANGELOG.md +23 -0
- data/README.md +39 -4
- data/chewy.gemspec +3 -2
- data/docker-compose.yml +15 -0
- data/gemfiles/base.gemfile +3 -3
- data/lib/chewy/errors.rb +3 -0
- data/lib/chewy/fields/root.rb +1 -1
- data/lib/chewy/index/actions.rb +5 -5
- data/lib/chewy/index/aliases.rb +1 -1
- data/lib/chewy/index/syncer.rb +1 -1
- data/lib/chewy/minitest/helpers.rb +1 -1
- data/lib/chewy/search/request.rb +4 -4
- data/lib/chewy/search/response.rb +7 -0
- data/lib/chewy/search/scrolling.rb +2 -1
- data/lib/chewy/strategy/delayed_sidekiq/scheduler.rb +33 -16
- data/lib/chewy/strategy/delayed_sidekiq/worker.rb +30 -6
- data/lib/chewy/strategy/delayed_sidekiq.rb +4 -4
- data/lib/chewy/version.rb +1 -1
- data/lib/chewy.rb +4 -0
- data/spec/chewy/elastic_client_spec.rb +1 -1
- data/spec/chewy/fields/base_spec.rb +2 -2
- data/spec/chewy/fields/time_fields_spec.rb +1 -1
- data/spec/chewy/index/actions_spec.rb +9 -9
- data/spec/chewy/index/aliases_spec.rb +1 -1
- data/spec/chewy/index/import/bulk_builder_spec.rb +2 -2
- data/spec/chewy/index/import/bulk_request_spec.rb +1 -1
- data/spec/chewy/index/import/routine_spec.rb +1 -1
- data/spec/chewy/index/import_spec.rb +15 -15
- data/spec/chewy/index/observe/callback_spec.rb +1 -1
- data/spec/chewy/index/specification_spec.rb +1 -4
- data/spec/chewy/index/syncer_spec.rb +1 -1
- data/spec/chewy/index_spec.rb +1 -1
- data/spec/chewy/journal_spec.rb +2 -2
- data/spec/chewy/minitest/helpers_spec.rb +1 -1
- data/spec/chewy/multi_search_spec.rb +1 -1
- data/spec/chewy/rake_helper_spec.rb +1 -1
- data/spec/chewy/rspec/update_index_spec.rb +1 -1
- data/spec/chewy/runtime_spec.rb +2 -2
- data/spec/chewy/search/loader_spec.rb +1 -1
- data/spec/chewy/search/pagination/kaminari_examples.rb +1 -1
- data/spec/chewy/search/request_spec.rb +1 -1
- data/spec/chewy/search/response_spec.rb +2 -2
- data/spec/chewy/search/scrolling_spec.rb +1 -1
- data/spec/chewy/search_spec.rb +1 -1
- data/spec/chewy/stash_spec.rb +1 -1
- data/spec/chewy/strategy/delayed_sidekiq_spec.rb +13 -7
- data/spec/chewy/strategy_spec.rb +1 -1
- data/spec/chewy_spec.rb +6 -5
- data/spec/spec_helper.rb +26 -0
- metadata +14 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe6459bb964c9d44912601a2a5abc6ea93ea7ac7be94c384673ade2ce68fb9e6
|
4
|
+
data.tar.gz: 397d2104f889f9e9232ed673b3fe5dc50fe4c13f1330b4ce9b1b1e45f9a11e16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebe662c3e11aaebd6fb8de8058ed9199d94b7eb80e7f4b6347c0fe98481c37cdb6be51e72d13645e627ae7d653d43c4bcd6a9a1f81b4eafdbb7371c814f2e847
|
7
|
+
data.tar.gz: 0e3b1d9b5eb0724fb1b2453d75e7980d9d7c1a3b341dca3934c366c7ba6ec5242bd9e647538486c9be6203d1ca9a5c6f18bcefcfc7ea64cdf8a31b7893af9f72
|
data/.github/CODEOWNERS
CHANGED
@@ -1 +1 @@
|
|
1
|
-
.github/workflows @toptal/
|
1
|
+
.github/workflows @toptal/sre
|
data/.github/workflows/ruby.yml
CHANGED
@@ -23,17 +23,29 @@ jobs:
|
|
23
23
|
env:
|
24
24
|
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
25
25
|
|
26
|
+
services:
|
27
|
+
redis:
|
28
|
+
# Docker Hub image
|
29
|
+
image: redis
|
30
|
+
ports:
|
31
|
+
- '6379:6379'
|
32
|
+
# Set health checks to wait until redis has started
|
33
|
+
options: >-
|
34
|
+
--health-cmd "redis-cli ping"
|
35
|
+
--health-interval 10s
|
36
|
+
--health-timeout 5s
|
37
|
+
--health-retries 5
|
26
38
|
steps:
|
27
39
|
- uses: actions/checkout@v4
|
28
40
|
- uses: ruby/setup-ruby@v1
|
29
41
|
with:
|
30
42
|
ruby-version: ${{ matrix.ruby }}
|
31
43
|
bundler-cache: true
|
32
|
-
- name:
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
44
|
+
- name: Start containers
|
45
|
+
run: |
|
46
|
+
docker compose up elasticsearch_test -d
|
47
|
+
sleep 15
|
48
|
+
|
37
49
|
- name: Tests
|
38
50
|
run: bundle exec rspec
|
39
51
|
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,29 @@
|
|
8
8
|
|
9
9
|
### Bugs Fixed
|
10
10
|
|
11
|
+
## 8.0.0-beta (2024-08-27)
|
12
|
+
|
13
|
+
### New Features
|
14
|
+
|
15
|
+
* [#962](https://github.com/toptal/chewy/pull/962): ElasticSearch v.8 support added
|
16
|
+
|
17
|
+
* `delete_all_enabled` setting introduced to align Chewy.massacre with wildcard indices deletion disabled in ES 8 by default
|
18
|
+
|
19
|
+
### Changes
|
20
|
+
|
21
|
+
### Bugs Fixed
|
22
|
+
|
23
|
+
## 7.6.0 (2024-05-03)
|
24
|
+
|
25
|
+
### Changes
|
26
|
+
|
27
|
+
* [#933](https://github.com/toptal/chewy/pull/933): Relax allowed `elasticsearch` dependency versions. ([@mjankowski][])
|
28
|
+
|
29
|
+
### Bugs Fixed
|
30
|
+
* [#937](https://github.com/toptal/chewy/pull/937): Fix for race condition while using the `delayed_sidekiq` strategy. Also, fix for Redis bloating in case of reindexing error ([@skcc321](https://github.com/skcc321))
|
31
|
+
|
32
|
+
* [#947](https://github.com/toptal/chewy/pull/947): Fix intermittent time-based failure in delayed sidekiq spec. ([@mjankowski][])
|
33
|
+
|
11
34
|
## 7.5.1 (2024-01-30)
|
12
35
|
|
13
36
|
### New Features
|
data/README.md
CHANGED
@@ -51,6 +51,7 @@ Chewy is compatible with MRI 3.0-3.2¹.
|
|
51
51
|
|
52
52
|
| Chewy version | Elasticsearch version |
|
53
53
|
| ------------- | ---------------------------------- |
|
54
|
+
| 8.0.0 | 8.x |
|
54
55
|
| 7.2.x | 7.x |
|
55
56
|
| 7.1.x | 7.x |
|
56
57
|
| 7.0.x | 6.8, 7.x |
|
@@ -97,7 +98,36 @@ development:
|
|
97
98
|
Make sure you have Elasticsearch up and running. You can [install](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html) it locally, but the easiest way is to use [Docker](https://www.docker.com/get-started):
|
98
99
|
|
99
100
|
```shell
|
100
|
-
$ docker run --rm --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:
|
101
|
+
$ docker run --rm --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" elasticsearch:8.15.0
|
102
|
+
```
|
103
|
+
|
104
|
+
### Security
|
105
|
+
|
106
|
+
Please note that starting from version 8 ElasticSearch has security features enabled by default.
|
107
|
+
Docker command above has it disabled for local testing convenience. If you want to enable it, omit
|
108
|
+
`"xpack.security.enabled=false"` part from Docker command, and run these command after starting container (container name `es8` assumed):
|
109
|
+
|
110
|
+
Reset password for `elastic` user:
|
111
|
+
```
|
112
|
+
docker container exec es8 '/usr/share/elasticsearch/bin/elasticsearch-reset-password' -u elastic
|
113
|
+
```
|
114
|
+
|
115
|
+
Extract CA certificate generated by ElasticSearch on first run:
|
116
|
+
```
|
117
|
+
docker container cp es8:/usr/share/elasticsearch/config/certs/http_ca.crt tmp/
|
118
|
+
```
|
119
|
+
|
120
|
+
And then add them to settings:
|
121
|
+
|
122
|
+
```yaml
|
123
|
+
# config/chewy.yml
|
124
|
+
development:
|
125
|
+
host: 'localhost:9200'
|
126
|
+
user: 'elastic'
|
127
|
+
password: 'SomeLongPassword'
|
128
|
+
transport_options:
|
129
|
+
ssl:
|
130
|
+
ca_file: './tmp/http_ca.crt'
|
101
131
|
```
|
102
132
|
|
103
133
|
### Index
|
@@ -776,9 +806,12 @@ Chewy.settings[:sidekiq] = {queue: :low}
|
|
776
806
|
|
777
807
|
#### `:delayed_sidekiq`
|
778
808
|
|
779
|
-
It accumulates
|
780
|
-
|
781
|
-
It supports `update_fields` option, so it will
|
809
|
+
It accumulates IDs of records to be reindexed during the latency window in Redis and then performs the reindexing of all accumulated records at once.
|
810
|
+
This strategy is very useful in the case of frequently mutated records.
|
811
|
+
It supports the `update_fields` option, so it will attempt to select just enough data from the database.
|
812
|
+
|
813
|
+
Keep in mind, this strategy does not guarantee reindexing in the event of Sidekiq worker termination or an error during the reindexing phase.
|
814
|
+
This behavior is intentional to prevent continuous growth of Redis db.
|
782
815
|
|
783
816
|
There are three options that can be defined in the index:
|
784
817
|
```ruby
|
@@ -938,6 +971,8 @@ Controller actions are wrapped with the configurable value of `Chewy.request_str
|
|
938
971
|
|
939
972
|
It is also a good idea to set up the `:bypass` strategy inside your test suite and import objects manually only when needed, and use `Chewy.massacre` when needed to flush test ES indices before every example. This will allow you to minimize unnecessary ES requests and reduce overhead.
|
940
973
|
|
974
|
+
Deprecation note: since version 8 wildcard removing of indices is disabled by default. You can enable it for a cluster with setting `action.destructive_requires_name` to false.
|
975
|
+
|
941
976
|
```ruby
|
942
977
|
RSpec.configure do |config|
|
943
978
|
config.before(:suite) do
|
data/chewy.gemspec
CHANGED
@@ -11,13 +11,14 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.description = 'Chewy provides functionality for Elasticsearch index handling, documents import mappings and chainable query DSL'
|
12
12
|
spec.homepage = 'https://github.com/toptal/chewy'
|
13
13
|
spec.license = 'MIT'
|
14
|
+
spec.required_ruby_version = '~> 3.0'
|
14
15
|
|
15
16
|
spec.files = `git ls-files`.split($RS)
|
16
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
18
|
spec.require_paths = ['lib']
|
18
19
|
|
19
|
-
spec.add_dependency 'activesupport', '>=
|
20
|
-
spec.add_dependency 'elasticsearch', '>=
|
20
|
+
spec.add_dependency 'activesupport', '>= 6.1'
|
21
|
+
spec.add_dependency 'elasticsearch', '>= 8.14', '< 9.0'
|
21
22
|
spec.add_dependency 'elasticsearch-dsl'
|
22
23
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
23
24
|
end
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
version: "3.4"
|
2
|
+
services:
|
3
|
+
elasticsearch_test:
|
4
|
+
image: "elasticsearch:8.15.0"
|
5
|
+
environment:
|
6
|
+
- bootstrap.memory_lock=${ES_MEMORY_LOCK:-false}
|
7
|
+
- "ES_JAVA_OPTS=-Xms${TEST_ES_HEAP_SIZE:-500m} -Xmx${TEST_ES_HEAP_SIZE:-500m}"
|
8
|
+
- discovery.type=single-node
|
9
|
+
- xpack.security.enabled=false
|
10
|
+
ports:
|
11
|
+
- "127.0.0.1:9250:9200"
|
12
|
+
ulimits:
|
13
|
+
nofile:
|
14
|
+
soft: 65536
|
15
|
+
hard: 65536
|
data/gemfiles/base.gemfile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
gem 'database_cleaner'
|
2
2
|
gem 'elasticsearch-extensions'
|
3
3
|
gem 'method_source'
|
4
|
-
gem 'mock_redis'
|
5
4
|
gem 'rake'
|
5
|
+
gem 'redis', require: false
|
6
6
|
gem 'rspec', '>= 3.7.0'
|
7
7
|
gem 'rspec-collection_matchers'
|
8
8
|
gem 'rspec-its'
|
9
|
-
gem 'rubocop', '1.
|
10
|
-
gem 'sqlite3'
|
9
|
+
gem 'rubocop', '1.65.1'
|
10
|
+
gem 'sqlite3', '~> 1.4'
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'unparser'
|
data/lib/chewy/errors.rb
CHANGED
data/lib/chewy/fields/root.rb
CHANGED
data/lib/chewy/index/actions.rb
CHANGED
@@ -32,7 +32,7 @@ module Chewy
|
|
32
32
|
#
|
33
33
|
def create(*args, **kwargs)
|
34
34
|
create!(*args, **kwargs)
|
35
|
-
rescue
|
35
|
+
rescue Elastic::Transport::Transport::Errors::BadRequest
|
36
36
|
false
|
37
37
|
end
|
38
38
|
|
@@ -83,9 +83,9 @@ module Chewy
|
|
83
83
|
result = client.indices.delete index: index_names.join(',')
|
84
84
|
Chewy.wait_for_status if result
|
85
85
|
result
|
86
|
-
# es-ruby >= 1.0.10 handles
|
86
|
+
# es-ruby >= 1.0.10 handles Elastic::Transport::Transport::Errors::NotFound
|
87
87
|
# by itself, rescue is for previous versions
|
88
|
-
rescue
|
88
|
+
rescue Elastic::Transport::Transport::Errors::NotFound
|
89
89
|
false
|
90
90
|
end
|
91
91
|
|
@@ -99,9 +99,9 @@ module Chewy
|
|
99
99
|
# UsersIndex.delete '01-2014' # deletes `users_01-2014` index
|
100
100
|
#
|
101
101
|
def delete!(suffix = nil)
|
102
|
-
# es-ruby >= 1.0.10 handles
|
102
|
+
# es-ruby >= 1.0.10 handles Elastic::Transport::Transport::Errors::NotFound
|
103
103
|
# by itself, so it is raised here
|
104
|
-
delete(suffix) or raise
|
104
|
+
delete(suffix) or raise Elastic::Transport::Transport::Errors::NotFound
|
105
105
|
end
|
106
106
|
|
107
107
|
# Deletes and recreates index. Supports suffixes.
|
data/lib/chewy/index/aliases.rb
CHANGED
data/lib/chewy/index/syncer.rb
CHANGED
@@ -213,7 +213,7 @@ module Chewy
|
|
213
213
|
@outdated_sync_field_type = mappings
|
214
214
|
.fetch('properties', {})
|
215
215
|
.fetch(@index.outdated_sync_field.to_s, {})['type']
|
216
|
-
rescue
|
216
|
+
rescue Elastic::Transport::Transport::Errors::NotFound
|
217
217
|
nil
|
218
218
|
end
|
219
219
|
end
|
data/lib/chewy/search/request.rb
CHANGED
@@ -46,7 +46,7 @@ module Chewy
|
|
46
46
|
|
47
47
|
delegate :hits, :wrappers, :objects, :records, :documents,
|
48
48
|
:object_hash, :record_hash, :document_hash,
|
49
|
-
:total, :max_score, :took, :timed_out?, to: :response
|
49
|
+
:total, :max_score, :took, :timed_out?, :terminated_early?, to: :response
|
50
50
|
delegate :each, :size, :to_a, :[], to: :wrappers
|
51
51
|
alias_method :to_ary, :to_a
|
52
52
|
alias_method :total_count, :total
|
@@ -854,7 +854,7 @@ module Chewy
|
|
854
854
|
else
|
855
855
|
Chewy.client.count(only(WHERE_STORAGES).render)['count']
|
856
856
|
end
|
857
|
-
rescue
|
857
|
+
rescue Elastic::Transport::Transport::Errors::NotFound
|
858
858
|
0
|
859
859
|
end
|
860
860
|
|
@@ -891,7 +891,7 @@ module Chewy
|
|
891
891
|
def first(limit = UNDEFINED)
|
892
892
|
request_limit = limit == UNDEFINED ? 1 : limit
|
893
893
|
|
894
|
-
if performed? && (request_limit <= size || size == total)
|
894
|
+
if performed? && (terminated_early? || request_limit <= size || size == total)
|
895
895
|
limit == UNDEFINED ? wrappers.first : wrappers.first(limit)
|
896
896
|
else
|
897
897
|
result = except(EXTRA_STORAGES).limit(request_limit).to_a
|
@@ -1035,7 +1035,7 @@ module Chewy
|
|
1035
1035
|
request_body = render.merge(additional)
|
1036
1036
|
ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: request_body) do
|
1037
1037
|
Chewy.client.search(request_body)
|
1038
|
-
rescue
|
1038
|
+
rescue Elastic::Transport::Transport::Errors::NotFound
|
1039
1039
|
{}
|
1040
1040
|
end
|
1041
1041
|
end
|
@@ -47,6 +47,13 @@ module Chewy
|
|
47
47
|
@timed_out ||= @body['timed_out']
|
48
48
|
end
|
49
49
|
|
50
|
+
# Has the request been terminated early?
|
51
|
+
#
|
52
|
+
# @return [true, false]
|
53
|
+
def terminated_early?
|
54
|
+
@terminated_early ||= @body['terminated_early']
|
55
|
+
end
|
56
|
+
|
50
57
|
# The `suggest` response part. Returns empty hash if suggests
|
51
58
|
# were not requested.
|
52
59
|
#
|
@@ -39,7 +39,8 @@ module Chewy
|
|
39
39
|
hits = hits.first(last_batch_size) if last_batch_size != 0 && fetched >= total
|
40
40
|
yield(hits) if hits.present?
|
41
41
|
scroll_id = result['_scroll_id']
|
42
|
-
|
42
|
+
|
43
|
+
break if result['terminated_early'] || fetched >= total
|
43
44
|
|
44
45
|
result = perform_scroll(scroll: scroll, scroll_id: scroll_id)
|
45
46
|
end
|
@@ -12,13 +12,43 @@ module Chewy
|
|
12
12
|
class DelayedSidekiq
|
13
13
|
require_relative 'worker'
|
14
14
|
|
15
|
+
LUA_SCRIPT = <<~LUA
|
16
|
+
local timechunk_key = KEYS[1]
|
17
|
+
local timechunks_key = KEYS[2]
|
18
|
+
local serialize_data = ARGV[1]
|
19
|
+
local at = ARGV[2]
|
20
|
+
local ttl = tonumber(ARGV[3])
|
21
|
+
|
22
|
+
local schedule_job = false
|
23
|
+
|
24
|
+
-- Check if the 'sadd?' method is available
|
25
|
+
if redis.call('exists', 'sadd?') == 1 then
|
26
|
+
redis.call('sadd?', timechunk_key, serialize_data)
|
27
|
+
else
|
28
|
+
redis.call('sadd', timechunk_key, serialize_data)
|
29
|
+
end
|
30
|
+
|
31
|
+
-- Set expiration for timechunk_key
|
32
|
+
redis.call('expire', timechunk_key, ttl)
|
33
|
+
|
34
|
+
-- Check if timechunk_key exists in the sorted set
|
35
|
+
if not redis.call('zrank', timechunks_key, timechunk_key) then
|
36
|
+
-- Add timechunk_key to the sorted set
|
37
|
+
redis.call('zadd', timechunks_key, at, timechunk_key)
|
38
|
+
-- Set expiration for timechunks_key
|
39
|
+
redis.call('expire', timechunks_key, ttl)
|
40
|
+
schedule_job = true
|
41
|
+
end
|
42
|
+
|
43
|
+
return schedule_job
|
44
|
+
LUA
|
45
|
+
|
15
46
|
class Scheduler
|
16
47
|
DEFAULT_TTL = 60 * 60 * 24 # in seconds
|
17
48
|
DEFAULT_LATENCY = 10
|
18
49
|
DEFAULT_MARGIN = 2
|
19
50
|
DEFAULT_QUEUE = 'chewy'
|
20
51
|
KEY_PREFIX = 'chewy:delayed_sidekiq'
|
21
|
-
ALL_SETS_KEY = "#{KEY_PREFIX}:all_sets".freeze
|
22
52
|
FALLBACK_FIELDS = 'all'
|
23
53
|
FIELDS_IDS_SEPARATOR = ';'
|
24
54
|
IDS_SEPARATOR = ','
|
@@ -67,21 +97,8 @@ module Chewy
|
|
67
97
|
# | chewy:delayed_sidekiq:CitiesIndex:1679347868
|
68
98
|
def postpone
|
69
99
|
::Sidekiq.redis do |redis|
|
70
|
-
#
|
71
|
-
if redis.
|
72
|
-
redis.sadd?(ALL_SETS_KEY, timechunks_key)
|
73
|
-
redis.sadd?(timechunk_key, serialize_data)
|
74
|
-
else
|
75
|
-
redis.sadd(ALL_SETS_KEY, timechunks_key)
|
76
|
-
redis.sadd(timechunk_key, serialize_data)
|
77
|
-
end
|
78
|
-
|
79
|
-
redis.expire(timechunk_key, ttl)
|
80
|
-
|
81
|
-
unless redis.zrank(timechunks_key, timechunk_key)
|
82
|
-
redis.zadd(timechunks_key, at, timechunk_key)
|
83
|
-
redis.expire(timechunks_key, ttl)
|
84
|
-
|
100
|
+
# do the redis stuff in a single command to avoid concurrency issues
|
101
|
+
if redis.eval(LUA_SCRIPT, keys: [timechunk_key, timechunks_key], argv: [serialize_data, at, ttl])
|
85
102
|
::Sidekiq::Client.push(
|
86
103
|
'queue' => sidekiq_queue,
|
87
104
|
'at' => at + margin,
|
@@ -6,13 +6,40 @@ module Chewy
|
|
6
6
|
class Worker
|
7
7
|
include ::Sidekiq::Worker
|
8
8
|
|
9
|
+
LUA_SCRIPT = <<~LUA
|
10
|
+
local type = ARGV[1]
|
11
|
+
local score = tonumber(ARGV[2])
|
12
|
+
local prefix = ARGV[3]
|
13
|
+
local timechunks_key = prefix .. ":" .. type .. ":timechunks"
|
14
|
+
|
15
|
+
-- Get timechunk_keys with scores less than or equal to the specified score
|
16
|
+
local timechunk_keys = redis.call('zrangebyscore', timechunks_key, '-inf', score)
|
17
|
+
|
18
|
+
-- Get all members from the sets associated with the timechunk_keys
|
19
|
+
local members = {}
|
20
|
+
for _, timechunk_key in ipairs(timechunk_keys) do
|
21
|
+
local set_members = redis.call('smembers', timechunk_key)
|
22
|
+
for _, member in ipairs(set_members) do
|
23
|
+
table.insert(members, member)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
-- Remove timechunk_keys and their associated sets
|
28
|
+
for _, timechunk_key in ipairs(timechunk_keys) do
|
29
|
+
redis.call('del', timechunk_key)
|
30
|
+
end
|
31
|
+
|
32
|
+
-- Remove timechunks with scores less than or equal to the specified score
|
33
|
+
redis.call('zremrangebyscore', timechunks_key, '-inf', score)
|
34
|
+
|
35
|
+
return members
|
36
|
+
LUA
|
37
|
+
|
9
38
|
def perform(type, score, options = {})
|
10
39
|
options[:refresh] = !Chewy.disable_refresh_async if Chewy.disable_refresh_async
|
11
40
|
|
12
41
|
::Sidekiq.redis do |redis|
|
13
|
-
|
14
|
-
timechunk_keys = redis.zrangebyscore(timechunks_key, -1, score)
|
15
|
-
members = timechunk_keys.flat_map { |timechunk_key| redis.smembers(timechunk_key) }.compact
|
42
|
+
members = redis.eval(LUA_SCRIPT, keys: [], argv: [type, score, Scheduler::KEY_PREFIX])
|
16
43
|
|
17
44
|
# extract ids and fields & do the reset of records
|
18
45
|
ids, fields = extract_ids_and_fields(members)
|
@@ -22,9 +49,6 @@ module Chewy
|
|
22
49
|
index.strategy_config.delayed_sidekiq.reindex_wrapper.call do
|
23
50
|
options.any? ? index.import!(ids, **options) : index.import!(ids)
|
24
51
|
end
|
25
|
-
|
26
|
-
redis.del(timechunk_keys)
|
27
|
-
redis.zremrangebyscore(timechunks_key, -1, score)
|
28
52
|
end
|
29
53
|
end
|
30
54
|
|
@@ -9,11 +9,11 @@ module Chewy
|
|
9
9
|
# leak and potential flaky tests.
|
10
10
|
def self.clear_timechunks!
|
11
11
|
::Sidekiq.redis do |redis|
|
12
|
-
|
13
|
-
break if timechunk_sets.empty?
|
12
|
+
keys_to_delete = redis.keys("#{Scheduler::KEY_PREFIX}*")
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
# Delete keys one by one
|
15
|
+
keys_to_delete.each do |key|
|
16
|
+
redis.del(key)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/lib/chewy/version.rb
CHANGED
data/lib/chewy.rb
CHANGED
@@ -116,6 +116,10 @@ module Chewy
|
|
116
116
|
# Be careful, if current prefix is blank, this will destroy all the indexes.
|
117
117
|
#
|
118
118
|
def massacre
|
119
|
+
unless Chewy.settings[:delete_all_enabled]
|
120
|
+
raise FeatureDisabled, 'Feature disabled by default in ES 8. You can enable it in the cluster and set `delete_all_enabled` option in settings'
|
121
|
+
end
|
122
|
+
|
119
123
|
Chewy.client.indices.delete(index: [Chewy.configuration[:prefix], '*'].reject(&:blank?).join('_'))
|
120
124
|
Chewy.wait_for_status
|
121
125
|
end
|
@@ -5,7 +5,7 @@ describe Chewy::Fields::Base do
|
|
5
5
|
specify { expect(described_class.new('name', type: 'integer').options[:type]).to eq('integer') }
|
6
6
|
|
7
7
|
describe '#compose' do
|
8
|
-
let(:field) { described_class.new(:name, value:
|
8
|
+
let(:field) { described_class.new(:name, value: lambda(&:value)) }
|
9
9
|
|
10
10
|
specify { expect(field.compose(double(value: 'hello'))).to eq(name: 'hello') }
|
11
11
|
specify { expect(field.compose(double(value: %w[hello world]))).to eq(name: %w[hello world]) }
|
@@ -23,7 +23,7 @@ describe Chewy::Fields::Base do
|
|
23
23
|
|
24
24
|
context 'nested fields' do
|
25
25
|
before do
|
26
|
-
field.children.push(described_class.new(:subname1, value:
|
26
|
+
field.children.push(described_class.new(:subname1, value: lambda(&:subvalue1)))
|
27
27
|
field.children.push(described_class.new(:subname2, value: -> { subvalue2 }))
|
28
28
|
field.children.push(described_class.new(:subname3))
|
29
29
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Chewy::Index::Actions do
|
4
|
-
before {
|
4
|
+
before { drop_indices }
|
5
5
|
|
6
6
|
before do
|
7
7
|
stub_index :dummies
|
@@ -78,12 +78,12 @@ describe Chewy::Index::Actions do
|
|
78
78
|
specify do
|
79
79
|
expect do
|
80
80
|
DummiesIndex.create!
|
81
|
-
end.to raise_error(
|
81
|
+
end.to raise_error(Elastic::Transport::Transport::Errors::BadRequest).with_message(/already exists.*dummies/)
|
82
82
|
end
|
83
83
|
specify do
|
84
84
|
expect do
|
85
85
|
DummiesIndex.create!('2013')
|
86
|
-
end.to raise_error(
|
86
|
+
end.to raise_error(Elastic::Transport::Transport::Errors::BadRequest).with_message(/Invalid alias name \[dummies\]/)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -100,7 +100,7 @@ describe Chewy::Index::Actions do
|
|
100
100
|
specify do
|
101
101
|
expect do
|
102
102
|
DummiesIndex.create!('2013')
|
103
|
-
end.to raise_error(
|
103
|
+
end.to raise_error(Elastic::Transport::Transport::Errors::BadRequest).with_message(/already exists.*dummies_2013/)
|
104
104
|
end
|
105
105
|
specify { expect(DummiesIndex.create!('2014')['acknowledged']).to eq(true) }
|
106
106
|
|
@@ -190,11 +190,11 @@ describe Chewy::Index::Actions do
|
|
190
190
|
end
|
191
191
|
|
192
192
|
describe '.delete!' do
|
193
|
-
specify { expect { DummiesIndex.delete! }.to raise_error(
|
193
|
+
specify { expect { DummiesIndex.delete! }.to raise_error(Elastic::Transport::Transport::Errors::NotFound) }
|
194
194
|
specify do
|
195
195
|
expect do
|
196
196
|
DummiesIndex.delete!('2013')
|
197
|
-
end.to raise_error(
|
197
|
+
end.to raise_error(Elastic::Transport::Transport::Errors::NotFound)
|
198
198
|
end
|
199
199
|
|
200
200
|
context do
|
@@ -768,7 +768,7 @@ describe Chewy::Index::Actions do
|
|
768
768
|
.to receive(:clear_cache)
|
769
769
|
.and_call_original
|
770
770
|
expect { CitiesIndex.clear_cache({index: unexisted_index_name}) }
|
771
|
-
.to raise_error
|
771
|
+
.to raise_error Elastic::Transport::Transport::Errors::NotFound
|
772
772
|
end
|
773
773
|
end
|
774
774
|
|
@@ -820,7 +820,7 @@ describe Chewy::Index::Actions do
|
|
820
820
|
.to receive(:reindex)
|
821
821
|
.and_call_original
|
822
822
|
expect { CitiesIndex.reindex(source: unexisting_index, dest: dest_index_with_prefix) }
|
823
|
-
.to raise_error
|
823
|
+
.to raise_error Elastic::Transport::Transport::Errors::NotFound
|
824
824
|
end
|
825
825
|
end
|
826
826
|
|
@@ -883,7 +883,7 @@ describe Chewy::Index::Actions do
|
|
883
883
|
context 'index name' do
|
884
884
|
specify do
|
885
885
|
expect { CitiesIndex.update_mapping(unexisting_index, body_hash) }
|
886
|
-
.to raise_error
|
886
|
+
.to raise_error Elastic::Transport::Transport::Errors::NotFound
|
887
887
|
end
|
888
888
|
end
|
889
889
|
|
@@ -17,7 +17,7 @@ SimpleComment = Class.new do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
describe Chewy::Index::Import::BulkBuilder do
|
20
|
-
before {
|
20
|
+
before { drop_indices }
|
21
21
|
|
22
22
|
subject { described_class.new(index, to_index: to_index, delete: delete, fields: fields) }
|
23
23
|
let(:index) { CitiesIndex }
|
@@ -216,7 +216,7 @@ describe Chewy::Index::Import::BulkBuilder do
|
|
216
216
|
end
|
217
217
|
|
218
218
|
def do_raw_index_comment(options:, data:)
|
219
|
-
CommentsIndex.client.index(options.merge(index: 'comments',
|
219
|
+
CommentsIndex.client.index(options.merge(index: 'comments', refresh: true, body: data))
|
220
220
|
end
|
221
221
|
|
222
222
|
def raw_index_comment(comment)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Chewy::Index::Import do
|
4
|
-
before {
|
4
|
+
before { drop_indices }
|
5
5
|
|
6
6
|
before do
|
7
7
|
stub_model(:city)
|
@@ -204,10 +204,10 @@ describe Chewy::Index::Import do
|
|
204
204
|
end
|
205
205
|
end
|
206
206
|
|
207
|
-
let(:
|
207
|
+
let(:document_parsing_exception) do
|
208
208
|
{
|
209
|
-
'type' => '
|
210
|
-
'reason' => 'object mapping for [name] tried to parse field [name] as object, but found a concrete value'
|
209
|
+
'type' => 'document_parsing_exception',
|
210
|
+
'reason' => '[1:9] object mapping for [name] tried to parse field [name] as object, but found a concrete value'
|
211
211
|
}
|
212
212
|
end
|
213
213
|
|
@@ -215,7 +215,7 @@ describe Chewy::Index::Import do
|
|
215
215
|
payload = subscribe_notification
|
216
216
|
import dummy_cities, batch_size: 2
|
217
217
|
expect(payload).to eq(index: CitiesIndex,
|
218
|
-
errors: {index: {
|
218
|
+
errors: {index: {document_parsing_exception => %w[1 2 3]}},
|
219
219
|
import: {index: 3})
|
220
220
|
end
|
221
221
|
end
|
@@ -270,8 +270,8 @@ describe Chewy::Index::Import do
|
|
270
270
|
expect(payload).to eq(
|
271
271
|
errors: {
|
272
272
|
index: {{
|
273
|
-
'type' => '
|
274
|
-
'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
273
|
+
'type' => 'document_parsing_exception',
|
274
|
+
'reason' => '[1:27] object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
275
275
|
} => %w[2 4]}
|
276
276
|
},
|
277
277
|
import: {index: 6},
|
@@ -293,8 +293,8 @@ describe Chewy::Index::Import do
|
|
293
293
|
expect(payload).to eq(
|
294
294
|
errors: {
|
295
295
|
index: {{
|
296
|
-
'type' => '
|
297
|
-
'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
296
|
+
'type' => 'document_parsing_exception',
|
297
|
+
'reason' => '[1:27] object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
298
298
|
} => %w[2 4]}
|
299
299
|
},
|
300
300
|
import: {index: 6},
|
@@ -319,8 +319,8 @@ describe Chewy::Index::Import do
|
|
319
319
|
expect(payload).to eq(
|
320
320
|
errors: {
|
321
321
|
index: {{
|
322
|
-
'type' => '
|
323
|
-
'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
322
|
+
'type' => 'document_parsing_exception',
|
323
|
+
'reason' => '[1:27] object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
324
324
|
} => %w[2 4]}
|
325
325
|
},
|
326
326
|
import: {index: 6},
|
@@ -383,8 +383,8 @@ describe Chewy::Index::Import do
|
|
383
383
|
|
384
384
|
# Full match doesn't work here.
|
385
385
|
expect(payload[:errors][:update].keys).to match([
|
386
|
-
hash_including('type' => 'document_missing_exception', 'reason' => '[
|
387
|
-
hash_including('type' => 'document_missing_exception', 'reason' => '[
|
386
|
+
hash_including('type' => 'document_missing_exception', 'reason' => '[1]: document missing'),
|
387
|
+
hash_including('type' => 'document_missing_exception', 'reason' => '[3]: document missing')
|
388
388
|
])
|
389
389
|
expect(payload[:errors][:update].values).to eq([['1'], ['3']])
|
390
390
|
expect(imported_cities).to match_array([
|
@@ -431,8 +431,8 @@ describe Chewy::Index::Import do
|
|
431
431
|
expect(payload).to eq(
|
432
432
|
errors: {
|
433
433
|
update: {{
|
434
|
-
'type' => '
|
435
|
-
'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
434
|
+
'type' => 'document_parsing_exception',
|
435
|
+
'reason' => '[1:26] object mapping for [object] tried to parse field [object] as object, but found a concrete value'
|
436
436
|
} => %w[2 4]}
|
437
437
|
},
|
438
438
|
import: {index: 6},
|
@@ -21,7 +21,7 @@ describe Chewy::Index::Observe::Callback do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
context 'when executable is has arity 1' do
|
24
|
-
let(:executable) {
|
24
|
+
let(:executable) { lambda(&:population) }
|
25
25
|
|
26
26
|
it 'calls exectuable within context' do
|
27
27
|
expect(callback.call(city)).to eq(city.population)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Chewy::Index::Specification do
|
4
|
-
before {
|
4
|
+
before { drop_indices }
|
5
5
|
|
6
6
|
let(:index1) do
|
7
7
|
stub_index(:places) do
|
@@ -46,7 +46,6 @@ describe Chewy::Index::Specification do
|
|
46
46
|
specify do
|
47
47
|
expect { specification1.lock! }.to change { Chewy::Stash::Specification.all.hits }.from([]).to([{
|
48
48
|
'_index' => 'chewy_specifications',
|
49
|
-
'_type' => '_doc',
|
50
49
|
'_id' => 'places',
|
51
50
|
'_score' => 1.0,
|
52
51
|
'_source' => {'specification' => Base64.encode64({
|
@@ -62,7 +61,6 @@ describe Chewy::Index::Specification do
|
|
62
61
|
specify do
|
63
62
|
expect { specification5.lock! }.to change { Chewy::Stash::Specification.all.hits }.to([{
|
64
63
|
'_index' => 'chewy_specifications',
|
65
|
-
'_type' => '_doc',
|
66
64
|
'_id' => 'places',
|
67
65
|
'_score' => 1.0,
|
68
66
|
'_source' => {'specification' => Base64.encode64({
|
@@ -71,7 +69,6 @@ describe Chewy::Index::Specification do
|
|
71
69
|
}.to_json)}
|
72
70
|
}, {
|
73
71
|
'_index' => 'chewy_specifications',
|
74
|
-
'_type' => '_doc',
|
75
72
|
'_id' => 'namespace/cities',
|
76
73
|
'_score' => 1.0,
|
77
74
|
'_source' => {'specification' => Base64.encode64({
|
data/spec/chewy/index_spec.rb
CHANGED
data/spec/chewy/journal_spec.rb
CHANGED
@@ -21,7 +21,7 @@ describe Chewy::Journal do
|
|
21
21
|
default_import_options journal: true
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
drop_indices
|
25
25
|
Chewy.settings[:prefix] = 'some_prefix'
|
26
26
|
Timecop.freeze(time)
|
27
27
|
end
|
@@ -145,7 +145,7 @@ describe Chewy::Journal do
|
|
145
145
|
end
|
146
146
|
|
147
147
|
context do
|
148
|
-
before {
|
148
|
+
before { drop_indices }
|
149
149
|
before do
|
150
150
|
stub_model(:city) do
|
151
151
|
update_index 'cities', :self
|
data/spec/chewy/runtime_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Chewy::Runtime do
|
4
4
|
describe '.version' do
|
5
5
|
specify { expect(described_class.version).to be_a(described_class::Version) }
|
6
|
-
specify { expect(described_class.version).to be >= '
|
7
|
-
specify { expect(described_class.version).to be < '
|
6
|
+
specify { expect(described_class.version).to be >= '8.0' }
|
7
|
+
specify { expect(described_class.version).to be < '9.0' }
|
8
8
|
end
|
9
9
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Chewy::Search::Response, :orm do
|
4
|
-
before {
|
4
|
+
before { drop_indices }
|
5
5
|
|
6
6
|
before do
|
7
7
|
stub_model(:city)
|
@@ -39,7 +39,7 @@ describe Chewy::Search::Response, :orm do
|
|
39
39
|
specify { expect(subject.hits).to all be_a(Hash) }
|
40
40
|
specify do
|
41
41
|
expect(subject.hits.flat_map(&:keys).uniq)
|
42
|
-
.to match_array(%w[_id _index
|
42
|
+
.to match_array(%w[_id _index _score _source sort])
|
43
43
|
end
|
44
44
|
|
45
45
|
context do
|
data/spec/chewy/search_spec.rb
CHANGED
data/spec/chewy/stash_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
if defined?(Sidekiq)
|
4
4
|
require 'sidekiq/testing'
|
5
|
-
require '
|
5
|
+
require 'redis'
|
6
6
|
|
7
7
|
describe Chewy::Strategy::DelayedSidekiq do
|
8
8
|
around do |example|
|
@@ -10,9 +10,10 @@ if defined?(Sidekiq)
|
|
10
10
|
end
|
11
11
|
|
12
12
|
before do
|
13
|
-
redis =
|
13
|
+
redis = Redis.new
|
14
14
|
allow(Sidekiq).to receive(:redis).and_yield(redis)
|
15
15
|
Sidekiq::Worker.clear_all
|
16
|
+
described_class.clear_timechunks!
|
16
17
|
end
|
17
18
|
|
18
19
|
before do
|
@@ -35,7 +36,7 @@ if defined?(Sidekiq)
|
|
35
36
|
|
36
37
|
it "respects 'refresh: false' options" do
|
37
38
|
allow(Chewy).to receive(:disable_refresh_async).and_return(true)
|
38
|
-
expect(CitiesIndex).to receive(:import!).with([city.id, other_city.id], refresh: false)
|
39
|
+
expect(CitiesIndex).to receive(:import!).with(match_array([city.id, other_city.id]), refresh: false)
|
39
40
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [city.id, other_city.id])
|
40
41
|
scheduler.postpone
|
41
42
|
Chewy::Strategy::DelayedSidekiq::Worker.drain
|
@@ -47,7 +48,7 @@ if defined?(Sidekiq)
|
|
47
48
|
expect(Sidekiq::Client).to receive(:push).with(
|
48
49
|
hash_including(
|
49
50
|
'queue' => 'chewy',
|
50
|
-
'at' =>
|
51
|
+
'at' => expected_at_time.to_i,
|
51
52
|
'class' => Chewy::Strategy::DelayedSidekiq::Worker,
|
52
53
|
'args' => ['CitiesIndex', an_instance_of(Integer)]
|
53
54
|
)
|
@@ -62,6 +63,11 @@ if defined?(Sidekiq)
|
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
66
|
+
|
67
|
+
def expected_at_time
|
68
|
+
target = described_class::Scheduler::DEFAULT_LATENCY.seconds.from_now.to_i
|
69
|
+
target - (target % described_class::Scheduler::DEFAULT_LATENCY) + described_class::Scheduler::DEFAULT_MARGIN.seconds
|
70
|
+
end
|
65
71
|
end
|
66
72
|
|
67
73
|
context 'with custom config' do
|
@@ -103,7 +109,7 @@ if defined?(Sidekiq)
|
|
103
109
|
context 'two reindex call within the timewindow' do
|
104
110
|
it 'accumulates all ids does the reindex one time' do
|
105
111
|
Timecop.freeze do
|
106
|
-
expect(CitiesIndex).to receive(:import!).with([
|
112
|
+
expect(CitiesIndex).to receive(:import!).with(match_array([city.id, other_city.id])).once
|
107
113
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [city.id])
|
108
114
|
scheduler.postpone
|
109
115
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [other_city.id])
|
@@ -115,7 +121,7 @@ if defined?(Sidekiq)
|
|
115
121
|
context 'one call with update_fields another one without update_fields' do
|
116
122
|
it 'does reindex of all fields' do
|
117
123
|
Timecop.freeze do
|
118
|
-
expect(CitiesIndex).to receive(:import!).with([
|
124
|
+
expect(CitiesIndex).to receive(:import!).with(match_array([city.id, other_city.id])).once
|
119
125
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [city.id], update_fields: ['name'])
|
120
126
|
scheduler.postpone
|
121
127
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [other_city.id])
|
@@ -128,7 +134,7 @@ if defined?(Sidekiq)
|
|
128
134
|
context 'both calls with different update fields' do
|
129
135
|
it 'deos reindex with union of fields' do
|
130
136
|
Timecop.freeze do
|
131
|
-
expect(CitiesIndex).to receive(:import!).with([
|
137
|
+
expect(CitiesIndex).to receive(:import!).with(match_array([city.id, other_city.id]), update_fields: match_array(%w[name description])).once
|
132
138
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [city.id], update_fields: ['name'])
|
133
139
|
scheduler.postpone
|
134
140
|
scheduler = Chewy::Strategy::DelayedSidekiq::Scheduler.new(CitiesIndex, [other_city.id], update_fields: ['description'])
|
data/spec/chewy/strategy_spec.rb
CHANGED
data/spec/chewy_spec.rb
CHANGED
@@ -31,8 +31,8 @@ describe Chewy do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
before {
|
34
|
+
xdescribe '.massacre' do
|
35
|
+
before { drop_indices }
|
36
36
|
|
37
37
|
before do
|
38
38
|
allow(Chewy).to receive_messages(configuration: Chewy.configuration.merge(prefix: 'prefix1'))
|
@@ -40,7 +40,7 @@ describe Chewy do
|
|
40
40
|
allow(Chewy).to receive_messages(configuration: Chewy.configuration.merge(prefix: 'prefix2'))
|
41
41
|
stub_index(:developers).create!
|
42
42
|
|
43
|
-
|
43
|
+
drop_indices
|
44
44
|
|
45
45
|
allow(Chewy).to receive_messages(configuration: Chewy.configuration.merge(prefix: 'prefix1'))
|
46
46
|
end
|
@@ -84,7 +84,8 @@ describe Chewy do
|
|
84
84
|
# To avoid flaky issues when previous specs were run
|
85
85
|
allow(Chewy::Index).to receive(:descendants).and_return([CitiesIndex, PlacesIndex])
|
86
86
|
|
87
|
-
|
87
|
+
CitiesIndex.delete
|
88
|
+
PlacesIndex.delete
|
88
89
|
end
|
89
90
|
|
90
91
|
specify do
|
@@ -111,7 +112,7 @@ describe Chewy do
|
|
111
112
|
expect(CitiesIndex.exists?).to eq true
|
112
113
|
expect(PlacesIndex.exists?).to eq true
|
113
114
|
|
114
|
-
expect { Chewy.create_indices! }.to raise_error(
|
115
|
+
expect { Chewy.create_indices! }.to raise_error(Elastic::Transport::Transport::Errors::BadRequest)
|
115
116
|
end
|
116
117
|
end
|
117
118
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -28,6 +28,32 @@ Chewy.settings = {
|
|
28
28
|
}
|
29
29
|
}
|
30
30
|
|
31
|
+
# To work with security enabled:
|
32
|
+
#
|
33
|
+
# user = ENV['ES_USER'] || 'elastic'
|
34
|
+
# password = ENV['ES_PASSWORD'] || ''
|
35
|
+
# ca_cert = ENV['ES_CA_CERT'] || './tmp/http_ca.crt'
|
36
|
+
#
|
37
|
+
# Chewy.settings.merge!(
|
38
|
+
# user: user,
|
39
|
+
# password: password,
|
40
|
+
# transport_options: {
|
41
|
+
# ssl: {
|
42
|
+
# ca_file: ca_cert
|
43
|
+
# }
|
44
|
+
# }
|
45
|
+
# )
|
46
|
+
|
47
|
+
# Low-level substitute for now-obsolete drop_indices
|
48
|
+
def drop_indices
|
49
|
+
response = Chewy.client.cat.indices
|
50
|
+
indices = response.body.lines.map { |line| line.split[2] }
|
51
|
+
return if indices.blank?
|
52
|
+
|
53
|
+
Chewy.client.indices.delete(index: indices)
|
54
|
+
Chewy.wait_for_status
|
55
|
+
end
|
56
|
+
|
31
57
|
# Chewy.transport_logger = Logger.new(STDERR)
|
32
58
|
|
33
59
|
RSpec.configure do |config|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chewy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 8.0.0.pre.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toptal, LLC
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-09-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -17,34 +17,34 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '6.1'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '6.1'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: elasticsearch
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: '8.14'
|
35
35
|
- - "<"
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: '9.0'
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
42
|
- - ">="
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
44
|
+
version: '8.14'
|
45
45
|
- - "<"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: '9.0'
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: elasticsearch-dsl
|
50
50
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- README.md
|
89
89
|
- Rakefile
|
90
90
|
- chewy.gemspec
|
91
|
+
- docker-compose.yml
|
91
92
|
- filters
|
92
93
|
- gemfiles/base.gemfile
|
93
94
|
- gemfiles/rails.6.1.activerecord.gemfile
|
@@ -311,16 +312,16 @@ require_paths:
|
|
311
312
|
- lib
|
312
313
|
required_ruby_version: !ruby/object:Gem::Requirement
|
313
314
|
requirements:
|
314
|
-
- - "
|
315
|
+
- - "~>"
|
315
316
|
- !ruby/object:Gem::Version
|
316
|
-
version: '0'
|
317
|
+
version: '3.0'
|
317
318
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
318
319
|
requirements:
|
319
|
-
- - "
|
320
|
+
- - ">"
|
320
321
|
- !ruby/object:Gem::Version
|
321
|
-
version:
|
322
|
+
version: 1.3.1
|
322
323
|
requirements: []
|
323
|
-
rubygems_version: 3.
|
324
|
+
rubygems_version: 3.4.10
|
324
325
|
signing_key:
|
325
326
|
specification_version: 4
|
326
327
|
summary: Elasticsearch ODM client wrapper
|