search_flip 3.3.0 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +3 -2
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +13 -0
- data/README.md +12 -1
- data/docker-compose.yml +1 -0
- data/lib/search_flip/connection.rb +5 -5
- data/lib/search_flip/criteria.rb +36 -9
- data/lib/search_flip/http_client.rb +30 -5
- data/lib/search_flip/index.rb +8 -4
- data/lib/search_flip/version.rb +1 -1
- data/lib/search_flip.rb +8 -3
- data/spec/search_flip/aws_sigv4_plugin_spec.rb +6 -4
- data/spec/search_flip/bulk_spec.rb +5 -8
- data/spec/search_flip/connection_spec.rb +12 -5
- data/spec/search_flip/criteria_spec.rb +44 -9
- data/spec/search_flip/http_client_spec.rb +7 -3
- data/spec/search_flip/index_spec.rb +12 -4
- data/spec/spec_helper.rb +3 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a241c0ab86244a53caab6b7d8dbcd8f441d9e7fc40837cc9afa7f57e6c7e5da0
|
4
|
+
data.tar.gz: f42562bd8af88780accd33c91c112c9f81b42de8945aa956c118b7faff75c6f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad60516d947d060ca1fe049a80059c18e9deb76f7c380b0279cd11cd5b5e0fb811d3a46a12220fd731b793ce1a6728f23e6cb242410f584d040e874a2bed7d78
|
7
|
+
data.tar.gz: 415962179b2e3ead79296851746b5f4892bdfbce64d09ae6ef2a2f0df83fa265b1c00a8a549d42013911eaff7ecc0b0460d20ef5c72d096f070d1adce4d0797c
|
data/.github/workflows/test.yml
CHANGED
@@ -12,15 +12,17 @@ jobs:
|
|
12
12
|
- docker.elastic.co/elasticsearch/elasticsearch:6.7.0
|
13
13
|
- docker.elastic.co/elasticsearch/elasticsearch:7.0.0
|
14
14
|
- docker.elastic.co/elasticsearch/elasticsearch:7.11.2
|
15
|
+
- docker.elastic.co/elasticsearch/elasticsearch:8.1.1
|
15
16
|
ruby:
|
16
|
-
- 2.5
|
17
17
|
- 2.6
|
18
18
|
- 2.7
|
19
|
+
- 3.0
|
19
20
|
services:
|
20
21
|
elasticsearch:
|
21
22
|
image: ${{ matrix.elasticsearch }}
|
22
23
|
env:
|
23
24
|
discovery.type: single-node
|
25
|
+
xpack.security.enabled: false
|
24
26
|
ports:
|
25
27
|
- 9200:9200
|
26
28
|
steps:
|
@@ -30,6 +32,5 @@ jobs:
|
|
30
32
|
ruby-version: ${{ matrix.ruby }}
|
31
33
|
- run: gem install bundler
|
32
34
|
- run: bundle
|
33
|
-
- run: sleep 10
|
34
35
|
- run: bundle exec rspec
|
35
36
|
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
|
2
2
|
# CHANGELOG
|
3
3
|
|
4
|
+
## v3.6.0
|
5
|
+
|
6
|
+
* Support Elasticsearch v8
|
7
|
+
|
8
|
+
## v3.5.0
|
9
|
+
|
10
|
+
* Add `SearchFlip::Criteria#http_timeout` to allow specifying timeouts on
|
11
|
+
a query level
|
12
|
+
|
13
|
+
## v3.4.0
|
14
|
+
|
15
|
+
* Expose `Http#timeout` via `SearchFlip::HTTPClient`
|
16
|
+
|
4
17
|
## v3.3.0
|
5
18
|
|
6
19
|
* Update httprb
|
data/README.md
CHANGED
@@ -698,6 +698,14 @@ Specify a timeout to limit query processing time:
|
|
698
698
|
CommentIndex.timeout("3s").execute
|
699
699
|
```
|
700
700
|
|
701
|
+
* `http_timeout`
|
702
|
+
|
703
|
+
Specify a http timeout for the request which will be send to Elasticsearch:
|
704
|
+
|
705
|
+
```ruby
|
706
|
+
CommentIndex.http_timeout(3).execute
|
707
|
+
```
|
708
|
+
|
701
709
|
* `terminate_after`
|
702
710
|
|
703
711
|
Activate early query termination to stop query processing after the specified
|
@@ -756,7 +764,7 @@ end
|
|
756
764
|
This allows to use different clusters per index e.g. when migrating indices to
|
757
765
|
new versions of Elasticsearch.
|
758
766
|
|
759
|
-
You can specify basic auth, additional headers, etc via:
|
767
|
+
You can specify basic auth, additional headers, request timeouts, etc via:
|
760
768
|
|
761
769
|
```ruby
|
762
770
|
http_client = SearchFlip::HTTPClient.new
|
@@ -773,6 +781,9 @@ http_client = http_client.via("proxy.host", 8080)
|
|
773
781
|
# Custom headers
|
774
782
|
http_client = http_client.headers(key: "value")
|
775
783
|
|
784
|
+
# Timeouts
|
785
|
+
http_client = http_client.timeout(20)
|
786
|
+
|
776
787
|
SearchFlip::Connection.new(base_url: "...", http_client: http_client)
|
777
788
|
```
|
778
789
|
|
data/docker-compose.yml
CHANGED
@@ -64,7 +64,7 @@ module SearchFlip
|
|
64
64
|
def msearch(criterias)
|
65
65
|
payload = criterias.flat_map do |criteria|
|
66
66
|
[
|
67
|
-
SearchFlip::JSON.generate(index: criteria.target.index_name_with_prefix, type: criteria.target.type_name),
|
67
|
+
SearchFlip::JSON.generate(index: criteria.target.index_name_with_prefix, **(version.to_i < 8 ? { type: criteria.target.type_name } : {})),
|
68
68
|
SearchFlip::JSON.generate(criteria.request)
|
69
69
|
]
|
70
70
|
end
|
@@ -300,8 +300,8 @@ module SearchFlip
|
|
300
300
|
# @return [Boolean] Returns true or raises SearchFlip::ResponseError
|
301
301
|
|
302
302
|
def update_mapping(index_name, mapping, type_name: nil)
|
303
|
-
url = type_name ? type_url(index_name, type_name) : index_url(index_name)
|
304
|
-
params = type_name && version.to_f >= 6.7 ? { include_type_name: true } : {}
|
303
|
+
url = type_name && version.to_i < 8 ? type_url(index_name, type_name) : index_url(index_name)
|
304
|
+
params = type_name && version.to_f >= 6.7 && version.to_i < 8 ? { include_type_name: true } : {}
|
305
305
|
|
306
306
|
http_client.put("#{url}/_mapping", params: params, json: mapping)
|
307
307
|
|
@@ -318,8 +318,8 @@ module SearchFlip
|
|
318
318
|
# @return [Hash] The current type mapping
|
319
319
|
|
320
320
|
def get_mapping(index_name, type_name: nil)
|
321
|
-
url = type_name ? type_url(index_name, type_name) : index_url(index_name)
|
322
|
-
params = type_name && version.to_f >= 6.7 ? { include_type_name: true } : {}
|
321
|
+
url = type_name && version.to_i < 8 ? type_url(index_name, type_name) : index_url(index_name)
|
322
|
+
params = type_name && version.to_f >= 6.7 && version.to_i < 8 ? { include_type_name: true } : {}
|
323
323
|
|
324
324
|
response = http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params)
|
325
325
|
|
data/lib/search_flip/criteria.rb
CHANGED
@@ -26,7 +26,8 @@ module SearchFlip
|
|
26
26
|
|
27
27
|
attr_accessor :target, :profile_value, :source_value, :suggest_values, :includes_values,
|
28
28
|
:eager_load_values, :preload_values, :failsafe_value, :scroll_args, :terminate_after_value,
|
29
|
-
:timeout_value, :preference_value, :search_type_value, :routing_value, :track_total_hits_value
|
29
|
+
:timeout_value, :preference_value, :search_type_value, :routing_value, :track_total_hits_value,
|
30
|
+
:http_timeout_value
|
30
31
|
|
31
32
|
# Creates a new criteria while merging the attributes (constraints,
|
32
33
|
# settings, etc) of the current criteria with the attributes of another one
|
@@ -47,7 +48,7 @@ module SearchFlip
|
|
47
48
|
[
|
48
49
|
:profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :offset_value,
|
49
50
|
:limit_value, :scroll_args, :source_value, :preference_value, :search_type_value,
|
50
|
-
:routing_value, :track_total_hits_value, :explain_value
|
51
|
+
:routing_value, :track_total_hits_value, :explain_value, :http_timeout_value
|
51
52
|
].each do |name|
|
52
53
|
criteria.send(:"#{name}=", other.send(name)) unless other.send(name).nil?
|
53
54
|
end
|
@@ -148,6 +149,22 @@ module SearchFlip
|
|
148
149
|
end
|
149
150
|
end
|
150
151
|
|
152
|
+
# Specifies a http timeout, such that a SearchFlip::TimeoutError will be
|
153
|
+
# thrown when the request times out.
|
154
|
+
#
|
155
|
+
# @example
|
156
|
+
# ProductIndex.http_timeout(3).search("hello world")
|
157
|
+
#
|
158
|
+
# @param value [Fixnum] The timeout value
|
159
|
+
#
|
160
|
+
# @return [SearchFlip::Criteria] A newly created extended criteria
|
161
|
+
|
162
|
+
def http_timeout(value)
|
163
|
+
fresh.tap do |criteria|
|
164
|
+
criteria.http_timeout_value = value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
151
168
|
# Specifies early query termination, such that the processing will be
|
152
169
|
# stopped after the specified number of results has been accumulated.
|
153
170
|
#
|
@@ -330,10 +347,15 @@ module SearchFlip
|
|
330
347
|
dupped_request.delete(:from)
|
331
348
|
dupped_request.delete(:size)
|
332
349
|
|
350
|
+
http_request = connection.http_client
|
351
|
+
http_request = http_request.timeout(http_timeout_value) if http_timeout_value
|
352
|
+
|
333
353
|
if connection.version.to_i >= 5
|
334
|
-
connection.
|
354
|
+
url = connection.version.to_i < 8 ? target.type_url : target.index_url
|
355
|
+
|
356
|
+
http_request.post("#{url}/_delete_by_query", params: request_params.merge(params), json: dupped_request)
|
335
357
|
else
|
336
|
-
|
358
|
+
http_request.delete("#{target.type_url}/_query", params: request_params.merge(params), json: dupped_request)
|
337
359
|
end
|
338
360
|
|
339
361
|
target.refresh if SearchFlip::Config[:auto_refresh]
|
@@ -501,8 +523,8 @@ module SearchFlip
|
|
501
523
|
end
|
502
524
|
|
503
525
|
# Executes the search request for the current criteria, ie sends the
|
504
|
-
# request to Elasticsearch and returns the response. Connection
|
505
|
-
# response errors will be rescued if you specify the criteria to be
|
526
|
+
# request to Elasticsearch and returns the response. Connection, timeout
|
527
|
+
# and response errors will be rescued if you specify the criteria to be
|
506
528
|
# #failsafe, such that an empty response is returned instead.
|
507
529
|
#
|
508
530
|
# @example
|
@@ -590,6 +612,7 @@ module SearchFlip
|
|
590
612
|
|
591
613
|
def execute!
|
592
614
|
http_request = connection.http_client.headers(accept: "application/json")
|
615
|
+
http_request = http_request.timeout(http_timeout_value) if http_timeout_value
|
593
616
|
|
594
617
|
http_response =
|
595
618
|
if scroll_args && scroll_args[:id]
|
@@ -599,17 +622,21 @@ module SearchFlip
|
|
599
622
|
json: { scroll: scroll_args[:timeout], scroll_id: scroll_args[:id] }
|
600
623
|
)
|
601
624
|
elsif scroll_args
|
625
|
+
url = connection.version.to_i < 8 ? target.type_url : target.index_url
|
626
|
+
|
602
627
|
http_request.post(
|
603
|
-
"#{
|
628
|
+
"#{url}/_search",
|
604
629
|
params: request_params.merge(scroll: scroll_args[:timeout]),
|
605
630
|
json: request
|
606
631
|
)
|
607
632
|
else
|
608
|
-
|
633
|
+
url = connection.version.to_i < 8 ? target.type_url : target.index_url
|
634
|
+
|
635
|
+
http_request.post("#{url}/_search", params: request_params, json: request)
|
609
636
|
end
|
610
637
|
|
611
638
|
SearchFlip::Response.new(self, SearchFlip::JSON.parse(http_response.to_s))
|
612
|
-
rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
|
639
|
+
rescue SearchFlip::ConnectionError, SearchFlip::TimeoutError, SearchFlip::ResponseError => e
|
613
640
|
raise e unless failsafe_value
|
614
641
|
|
615
642
|
SearchFlip::Response.new(self, "took" => 0, "hits" => { "total" => 0, "hits" => [] })
|
@@ -1,7 +1,28 @@
|
|
1
1
|
module SearchFlip
|
2
|
-
# The SearchFlip::HTTPClient class wraps the http gem
|
3
|
-
#
|
4
|
-
# with
|
2
|
+
# The SearchFlip::HTTPClient class wraps the http gem and responsible for the
|
3
|
+
# http request/response handling, ie communicating with Elasticsearch. You
|
4
|
+
# only need to use it directly if you need authentication to communicate with
|
5
|
+
# Elasticsearch or if you want to set some custom http settings.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# http_client = SearchFlip::HTTPClient.new
|
9
|
+
#
|
10
|
+
# # Basic Auth
|
11
|
+
# http_client = http_client.basic_auth(user: "username", pass: "password")
|
12
|
+
#
|
13
|
+
# # Raw Auth Header
|
14
|
+
# http_client = http_client.auth("Bearer VGhlIEhUVFAgR2VtLCBST0NLUw")
|
15
|
+
#
|
16
|
+
# # Proxy Settings
|
17
|
+
# http_client = http_client.via("proxy.host", 8080)
|
18
|
+
#
|
19
|
+
# # Custom headers
|
20
|
+
# http_client = http_client.headers(key: "value")
|
21
|
+
#
|
22
|
+
# # Timeouts
|
23
|
+
# http_client = http_client.timeout(20)
|
24
|
+
#
|
25
|
+
# SearchFlip::Connection.new(base_url: "...", http_client: http_client)
|
5
26
|
|
6
27
|
class HTTPClient
|
7
28
|
attr_accessor :request, :plugins
|
@@ -14,11 +35,11 @@ module SearchFlip
|
|
14
35
|
class << self
|
15
36
|
extend Forwardable
|
16
37
|
|
17
|
-
def_delegators :new, :headers, :via, :basic_auth, :auth
|
38
|
+
def_delegators :new, :headers, :via, :basic_auth, :auth, :timeout
|
18
39
|
def_delegators :new, :get, :post, :put, :delete, :head
|
19
40
|
end
|
20
41
|
|
21
|
-
[:headers, :via, :basic_auth, :auth].each do |method|
|
42
|
+
[:headers, :via, :basic_auth, :auth, :timeout].each do |method|
|
22
43
|
define_method method do |*args|
|
23
44
|
dup.tap do |client|
|
24
45
|
client.request = request.send(method, *args)
|
@@ -45,6 +66,10 @@ module SearchFlip
|
|
45
66
|
response
|
46
67
|
rescue HTTP::ConnectionError => e
|
47
68
|
raise SearchFlip::ConnectionError, e.message
|
69
|
+
rescue HTTP::TimeoutError => e
|
70
|
+
raise SearchFlip::TimeoutError, e.message
|
71
|
+
rescue HTTP::Error => e
|
72
|
+
raise SearchFlip::HttpError, e.message
|
48
73
|
end
|
49
74
|
end
|
50
75
|
end
|
data/lib/search_flip/index.rb
CHANGED
@@ -254,7 +254,7 @@ module SearchFlip
|
|
254
254
|
:page, :per, :search, :highlight, :suggest, :custom, :find_in_batches, :find_results_in_batches,
|
255
255
|
:find_each, :find_each_result, :failsafe, :total_entries, :total_count, :timeout, :terminate_after,
|
256
256
|
:records, :results, :must, :must_not, :should, :preference, :search_type, :routing,
|
257
|
-
:track_total_hits, :explain
|
257
|
+
:track_total_hits, :explain, :http_timeout
|
258
258
|
|
259
259
|
# Override to specify the type name used within Elasticsearch. Recap,
|
260
260
|
# this gem uses an individual index for each index class, because
|
@@ -455,7 +455,8 @@ module SearchFlip
|
|
455
455
|
# @return [Hash] The specified document
|
456
456
|
|
457
457
|
def get(id, params = {})
|
458
|
-
|
458
|
+
url = connection.version.to_i < 8 ? type_url : "#{index_url}/_doc"
|
459
|
+
response = connection.http_client.headers(accept: "application/json").get("#{url}/#{id}", params: params)
|
459
460
|
|
460
461
|
SearchFlip::JSON.parse(response.to_s)
|
461
462
|
end
|
@@ -473,7 +474,8 @@ module SearchFlip
|
|
473
474
|
# @return [Hash] The raw response
|
474
475
|
|
475
476
|
def mget(request, params = {})
|
476
|
-
|
477
|
+
url = connection.version.to_i < 8 ? type_url : index_url
|
478
|
+
response = connection.http_client.headers(accept: "application/json").post("#{url}/_mget", json: request, params: params)
|
477
479
|
|
478
480
|
SearchFlip::JSON.parse(response.to_s)
|
479
481
|
end
|
@@ -631,7 +633,9 @@ module SearchFlip
|
|
631
633
|
bulk_max_mb: connection.bulk_max_mb
|
632
634
|
}
|
633
635
|
|
634
|
-
|
636
|
+
url = connection.version.to_i < 8 ? type_url : index_url
|
637
|
+
|
638
|
+
SearchFlip::Bulk.new("#{url}/_bulk", default_options.merge(options)) do |indexer|
|
635
639
|
yield indexer
|
636
640
|
end
|
637
641
|
|
data/lib/search_flip/version.rb
CHANGED
data/lib/search_flip.rb
CHANGED
@@ -33,10 +33,15 @@ require "search_flip/index"
|
|
33
33
|
require "search_flip/model"
|
34
34
|
|
35
35
|
module SearchFlip
|
36
|
-
class
|
37
|
-
class ConnectionError < StandardError; end
|
36
|
+
class Error < StandardError; end
|
38
37
|
|
39
|
-
class
|
38
|
+
class NotSupportedError < Error; end
|
39
|
+
|
40
|
+
class HttpError < Error; end
|
41
|
+
class ConnectionError < HttpError; end
|
42
|
+
class TimeoutError < HttpError; end
|
43
|
+
|
44
|
+
class ResponseError < Error
|
40
45
|
attr_reader :code, :body
|
41
46
|
|
42
47
|
def initialize(code:, body:)
|
@@ -16,10 +16,12 @@ RSpec.describe SearchFlip::AwsSigv4Plugin do
|
|
16
16
|
it "adds the signed headers to the request" do
|
17
17
|
Timecop.freeze Time.parse("2020-01-01 12:00:00 UTC") do
|
18
18
|
expect(client).to receive(:headers).with(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
an_object_matching(
|
20
|
+
"host" => "localhost",
|
21
|
+
"authorization" => /.*/,
|
22
|
+
"x-amz-content-sha256" => /.*/,
|
23
|
+
"x-amz-date" => /20200101T120000Z/
|
24
|
+
)
|
23
25
|
)
|
24
26
|
|
25
27
|
plugin.call(client, :get, "http://localhost/index")
|
@@ -60,18 +60,15 @@ RSpec.describe SearchFlip::Bulk do
|
|
60
60
|
|
61
61
|
it "uses the specified http_client" do
|
62
62
|
product = create(:product)
|
63
|
+
url = ProductIndex.connection.version.to_i < 8 ? ProductIndex.type_url : ProductIndex.index_url
|
63
64
|
|
64
|
-
stub_request(:put, "#{
|
65
|
-
.with(headers: { "X-Header" => "Value" })
|
66
|
-
.to_return(status: 500)
|
65
|
+
stub_request(:put, "#{url}/_bulk").with(headers: { "X-Header" => "Value" }).to_return(status: 200, body: "{}")
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
bulk.index product.id, ProductIndex.serialize(product)
|
71
|
-
end
|
67
|
+
ProductIndex.bulk http_client: ProductIndex.connection.http_client.headers("X-Header" => "Value") do |bulk|
|
68
|
+
bulk.index product.id, ProductIndex.serialize(product)
|
72
69
|
end
|
73
70
|
|
74
|
-
expect(
|
71
|
+
expect(WebMock).to have_requested(:put, "#{url}/_bulk").with(headers: { "X-Header" => "Value" })
|
75
72
|
end
|
76
73
|
|
77
74
|
it "transmits up to bulk_max_mb only" do
|
@@ -170,7 +170,7 @@ RSpec.describe SearchFlip::Connection do
|
|
170
170
|
it "freezes the specified index" do
|
171
171
|
connection = SearchFlip::Connection.new
|
172
172
|
|
173
|
-
if connection.version.to_f >= 6.6
|
173
|
+
if connection.version.to_f >= 6.6 && connection.version.to_i < 8
|
174
174
|
begin
|
175
175
|
connection.create_index("index_name")
|
176
176
|
connection.freeze_index("index_name")
|
@@ -187,7 +187,7 @@ RSpec.describe SearchFlip::Connection do
|
|
187
187
|
it "unfreezes the specified index" do
|
188
188
|
connection = SearchFlip::Connection.new
|
189
189
|
|
190
|
-
if connection.version.to_f >= 6.6
|
190
|
+
if connection.version.to_f >= 6.6 && connection.version.to_i < 8
|
191
191
|
begin
|
192
192
|
connection.create_index("index_name")
|
193
193
|
connection.freeze_index("index_name")
|
@@ -262,12 +262,19 @@ RSpec.describe SearchFlip::Connection do
|
|
262
262
|
begin
|
263
263
|
connection = SearchFlip::Connection.new
|
264
264
|
|
265
|
-
mapping = { "
|
265
|
+
mapping = { "properties" => { "id" => { "type" => "long" } } }
|
266
266
|
|
267
267
|
connection.create_index("index_name")
|
268
|
-
connection.update_mapping("index_name", mapping, type_name: "type_name")
|
269
268
|
|
270
|
-
|
269
|
+
if connection.version.to_i < 8
|
270
|
+
connection.update_mapping("index_name", { "type_name" => mapping }, type_name: "type_name")
|
271
|
+
|
272
|
+
expect(connection.get_mapping("index_name", type_name: "type_name")).to eq("index_name" => { "mappings" => { "type_name" => mapping } })
|
273
|
+
else
|
274
|
+
connection.update_mapping("index_name", mapping)
|
275
|
+
|
276
|
+
expect(connection.get_mapping("index_name")).to eq("index_name" => { "mappings" => mapping })
|
277
|
+
end
|
271
278
|
ensure
|
272
279
|
connection.delete_index("index_name") if connection.index_exists?("index_name")
|
273
280
|
end
|
@@ -97,7 +97,8 @@ RSpec.describe SearchFlip::Criteria do
|
|
97
97
|
methods = [
|
98
98
|
:profile_value, :failsafe_value, :terminate_after_value, :timeout_value,
|
99
99
|
:offset_value, :limit_value, :scroll_args, :source_value, :preference_value,
|
100
|
-
:search_type_value, :routing_value, :track_total_hits_value, :explain_value
|
100
|
+
:search_type_value, :routing_value, :track_total_hits_value, :explain_value,
|
101
|
+
:http_timeout_value
|
101
102
|
]
|
102
103
|
|
103
104
|
methods.each do |method|
|
@@ -191,6 +192,22 @@ RSpec.describe SearchFlip::Criteria do
|
|
191
192
|
end
|
192
193
|
end
|
193
194
|
|
195
|
+
describe "#http_timeout" do
|
196
|
+
it "sets the query timeout" do
|
197
|
+
http_client = double("client").as_null_object
|
198
|
+
allow(http_client).to receive(:timeout).and_return(http_client)
|
199
|
+
allow(http_client).to receive(:post).and_raise(SearchFlip::TimeoutError)
|
200
|
+
allow(ProductIndex.connection).to receive(:http_client).and_return(http_client)
|
201
|
+
|
202
|
+
expect { ProductIndex.http_timeout(1).execute }.to raise_error(SearchFlip::TimeoutError)
|
203
|
+
expect(http_client).to have_received(:timeout).with(1)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "executes without errors" do
|
207
|
+
expect { ProductIndex.http_timeout(1).execute }.not_to raise_error
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
194
211
|
describe "#terminate_after" do
|
195
212
|
it "sets the terminate after value" do
|
196
213
|
query = ProductIndex.terminate_after(1)
|
@@ -1204,13 +1221,19 @@ RSpec.describe SearchFlip::Criteria do
|
|
1204
1221
|
end
|
1205
1222
|
|
1206
1223
|
describe "#failsafe" do
|
1207
|
-
|
1208
|
-
|
1224
|
+
[SearchFlip::ConnectionError, SearchFlip::TimeoutError, SearchFlip::ResponseError.new(code: "code", body: "body")].each do |error|
|
1225
|
+
it "prevents #{error}" do
|
1226
|
+
http_client = double("client").as_null_object
|
1227
|
+
allow(http_client).to receive(:post).and_raise(error)
|
1228
|
+
allow(ProductIndex.connection).to receive(:http_client).and_return(http_client)
|
1229
|
+
|
1230
|
+
expect { ProductIndex.all.execute }.to raise_error(error)
|
1209
1231
|
|
1210
|
-
|
1232
|
+
query = ProductIndex.failsafe(true)
|
1211
1233
|
|
1212
|
-
|
1213
|
-
|
1234
|
+
expect(query.records).to eq([])
|
1235
|
+
expect(query.total_entries).to eq(0)
|
1236
|
+
end
|
1214
1237
|
end
|
1215
1238
|
end
|
1216
1239
|
|
@@ -1327,28 +1350,40 @@ RSpec.describe SearchFlip::Criteria do
|
|
1327
1350
|
|
1328
1351
|
describe "#preference" do
|
1329
1352
|
it "sets the preference" do
|
1330
|
-
|
1353
|
+
url = ProductIndex.connection.version.to_i < 8 ? "products/products" : "products"
|
1354
|
+
|
1355
|
+
stub_request(:post, "http://127.0.0.1:9200/#{url}/_search?preference=value")
|
1331
1356
|
.to_return(status: 200, headers: { content_type: "application/json" }, body: "{}")
|
1332
1357
|
|
1333
1358
|
ProductIndex.preference("value").execute
|
1359
|
+
|
1360
|
+
expect(WebMock).to have_requested(:post, "http://127.0.0.1:9200/#{url}/_search?preference=value")
|
1334
1361
|
end
|
1335
1362
|
end
|
1336
1363
|
|
1337
1364
|
describe "#search_type" do
|
1338
1365
|
it "sets the search_type" do
|
1339
|
-
|
1366
|
+
url = ProductIndex.connection.version.to_i < 8 ? "products/products" : "products"
|
1367
|
+
|
1368
|
+
stub_request(:post, "http://127.0.0.1:9200/#{url}/_search?search_type=value")
|
1340
1369
|
.to_return(status: 200, headers: { content_type: "application/json" }, body: "{}")
|
1341
1370
|
|
1342
1371
|
ProductIndex.search_type("value").execute
|
1372
|
+
|
1373
|
+
expect(WebMock).to have_requested(:post, "http://127.0.0.1:9200/#{url}/_search?search_type=value")
|
1343
1374
|
end
|
1344
1375
|
end
|
1345
1376
|
|
1346
1377
|
describe "#routing" do
|
1347
1378
|
it "sets the search_type" do
|
1348
|
-
|
1379
|
+
url = ProductIndex.connection.version.to_i < 8 ? "products/products" : "products"
|
1380
|
+
|
1381
|
+
stub_request(:post, "http://127.0.0.1:9200/#{url}/_search?routing=value")
|
1349
1382
|
.to_return(status: 200, headers: { content_type: "application/json" }, body: "{}")
|
1350
1383
|
|
1351
1384
|
ProductIndex.routing("value").execute
|
1385
|
+
|
1386
|
+
expect(WebMock).to have_requested(:post, "http://127.0.0.1:9200/#{url}/_search?routing=value")
|
1352
1387
|
end
|
1353
1388
|
end
|
1354
1389
|
end
|
@@ -7,7 +7,7 @@ class HttpTestRequest
|
|
7
7
|
self.calls = []
|
8
8
|
end
|
9
9
|
|
10
|
-
[:via, :basic_auth, :auth].each do |method|
|
10
|
+
[:headers, :via, :basic_auth, :auth, :timeout].each do |method|
|
11
11
|
define_method method do |*args|
|
12
12
|
dup.tap do |request|
|
13
13
|
request.calls = calls + [[method, args]]
|
@@ -20,7 +20,7 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
20
20
|
describe "delegation" do
|
21
21
|
subject { SearchFlip::HTTPClient }
|
22
22
|
|
23
|
-
[:headers, :via, :basic_auth, :auth].each do |method|
|
23
|
+
[:headers, :via, :basic_auth, :auth, :timeout].each do |method|
|
24
24
|
it { should delegate(method).to(:new) }
|
25
25
|
end
|
26
26
|
|
@@ -56,8 +56,12 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
[:via, :basic_auth, :auth].each do |method|
|
59
|
+
[:headers, :via, :basic_auth, :auth, :timeout].each do |method|
|
60
60
|
describe "##{method}" do
|
61
|
+
it "is understood by HTTP" do
|
62
|
+
expect(HTTP.respond_to?(method)).to eq(true)
|
63
|
+
end
|
64
|
+
|
61
65
|
it "creates a dupped instance" do
|
62
66
|
client = SearchFlip::HTTPClient.new
|
63
67
|
client.request = HttpTestRequest.new
|
@@ -14,7 +14,7 @@ RSpec.describe SearchFlip::Index do
|
|
14
14
|
:total_entries, :total_count, :terminate_after, :timeout, :records, :results,
|
15
15
|
:must, :must_not, :should, :find_each_result,
|
16
16
|
:find_results_in_batches, :preference, :search_type, :routing,
|
17
|
-
:track_total_hits, :explain
|
17
|
+
:track_total_hits, :explain, :http_timeout
|
18
18
|
]
|
19
19
|
|
20
20
|
methods.each do |method|
|
@@ -215,7 +215,11 @@ RSpec.describe SearchFlip::Index do
|
|
215
215
|
|
216
216
|
TestIndex.update_mapping
|
217
217
|
|
218
|
-
|
218
|
+
if TestIndex.connection.version.to_i < 8
|
219
|
+
expect(TestIndex.connection).to have_received(:update_mapping).with("test", { "test" => mapping }, type_name: "test")
|
220
|
+
else
|
221
|
+
expect(TestIndex.connection).to have_received(:update_mapping).with("test", mapping)
|
222
|
+
end
|
219
223
|
end
|
220
224
|
|
221
225
|
it "updates the mapping" do
|
@@ -268,7 +272,11 @@ RSpec.describe SearchFlip::Index do
|
|
268
272
|
|
269
273
|
TestIndex.get_mapping
|
270
274
|
|
271
|
-
|
275
|
+
if TestIndex.connection.version.to_i < 8
|
276
|
+
expect(TestIndex.connection).to have_received(:get_mapping).with("test", type_name: "test")
|
277
|
+
else
|
278
|
+
expect(TestIndex.connection).to have_received(:get_mapping).with("test")
|
279
|
+
end
|
272
280
|
end
|
273
281
|
|
274
282
|
it "returns the mapping" do
|
@@ -332,7 +340,7 @@ RSpec.describe SearchFlip::Index do
|
|
332
340
|
|
333
341
|
TestIndex.type_url
|
334
342
|
|
335
|
-
expect(TestIndex.connection).to have_received(:type_url).with("test", "test")
|
343
|
+
expect(TestIndex.connection).to have_received(:type_url).with("test", TestIndex.connection.version.to_i < 8 ? "test" : "_doc")
|
336
344
|
end
|
337
345
|
end
|
338
346
|
|
data/spec/spec_helper.rb
CHANGED
@@ -84,7 +84,7 @@ class CommentIndex
|
|
84
84
|
include SearchFlip::Index
|
85
85
|
|
86
86
|
def self.type_name
|
87
|
-
"comments"
|
87
|
+
connection.version.to_i < 8 ? "comments" : "_doc"
|
88
88
|
end
|
89
89
|
|
90
90
|
def self.index_name
|
@@ -134,7 +134,7 @@ class ProductIndex
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def self.type_name
|
137
|
-
"products"
|
137
|
+
connection.version.to_i < 8 ? "products" : "_doc"
|
138
138
|
end
|
139
139
|
|
140
140
|
def self.index_name
|
@@ -175,7 +175,7 @@ class TestIndex
|
|
175
175
|
end
|
176
176
|
|
177
177
|
def self.type_name
|
178
|
-
"test"
|
178
|
+
connection.version.to_i < 8 ? "test" : "_doc"
|
179
179
|
end
|
180
180
|
|
181
181
|
def self.index_name
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: search_flip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Vetter
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -302,7 +302,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
302
|
version: '0'
|
303
303
|
requirements: []
|
304
304
|
rubygems_version: 3.2.3
|
305
|
-
signing_key:
|
305
|
+
signing_key:
|
306
306
|
specification_version: 4
|
307
307
|
summary: Full-Featured Elasticsearch Ruby Client with a Chainable DSL
|
308
308
|
test_files:
|