caoutsearch 0.0.6 → 0.0.7
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/README.md +12 -8
- data/lib/caoutsearch/search/batch/search_after.rb +29 -9
- data/lib/caoutsearch/testing/mock_requests.rb +42 -16
- data/lib/caoutsearch/version.rb +1 -1
- metadata +212 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b63cce452c0627b856cb582366494c13b997a5e387ed03d2311b7f9ea8ea80f0
|
4
|
+
data.tar.gz: f9fe10e15528bef3d13b668fe6e2cc9e1a693c0d171797a463cf93ae4e3aca37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b5b638e8050f586b8140f729847d236e280c44e074b3300e746cf763fb861cfde3a5e5ac4071601782008aed363ed7130614914c25ec9f4c68f6542839145ad
|
7
|
+
data.tar.gz: 0b2e3ec3ff278bd7615d4b39e82738bb805c25264ae0cad3289c7c626e7a9e71b0cddc8cad1f9b28bbbb2e059061f800aa7df3189bae860da2fd39fee44cfd99
|
data/README.md
CHANGED
@@ -20,6 +20,10 @@ It is used in production in a robust application, updated and maintained for sev
|
|
20
20
|
Caoutsearch was inspired by awesome gems such as [elasticsearch-rails](https://github.com/elastic/elasticsearch-rails) or [search_flip](https://github.com/mrkamel/search_flip).
|
21
21
|
Depending on your search scenarios, they may better suite your needs.
|
22
22
|
|
23
|
+
## Documentation
|
24
|
+
|
25
|
+
Visit our [offical documentation](https://mon-territoire.github.io/caoutsearch) to understand how to use Caoutsearch.
|
26
|
+
|
23
27
|
## Installation
|
24
28
|
|
25
29
|
Add the gem in your Gemfile:
|
@@ -46,7 +50,6 @@ end
|
|
46
50
|
ArticleIndex.reindex(:tags)
|
47
51
|
```
|
48
52
|
|
49
|
-
|
50
53
|
```ruby
|
51
54
|
class ArticleSearch < Caoutsearch::Search::Base
|
52
55
|
filter :title, as: :match
|
@@ -66,15 +69,10 @@ end
|
|
66
69
|
ArticleSearch.search(published_on: [["now-1y", nil]]).aggregate(:popular_tags)
|
67
70
|
```
|
68
71
|
|
69
|
-
|
70
|
-
## Documentation
|
71
|
-
|
72
|
-
Visit our [offical documentation](https://mon-territoire.github.io/caoutsearch) to understand how to use Caoutsearch.
|
73
|
-
|
74
72
|
## Contributing
|
75
73
|
|
76
|
-
1. Don't hesitate to submit your feature/idea/fix in [issues](https://github.com/
|
77
|
-
2. Fork the [repository](https://github.com/
|
74
|
+
1. Don't hesitate to submit your feature/idea/fix in [issues](https://github.com/inkstak/activejob-status)
|
75
|
+
2. Fork the [repository](https://github.com/inkstak/activejob-status)
|
78
76
|
3. Create your feature branch
|
79
77
|
4. Ensure RSpec & Rubocop are passing
|
80
78
|
4. Create a pull request
|
@@ -87,6 +85,12 @@ bundle exec rubocop
|
|
87
85
|
bundle exec standardrb
|
88
86
|
```
|
89
87
|
|
88
|
+
To run RSpec against various version of Rails dependencies:
|
89
|
+
```bash
|
90
|
+
bundle exec appraisal install
|
91
|
+
bundle exec appraisal rspec
|
92
|
+
```
|
93
|
+
|
90
94
|
All of them can be run with:
|
91
95
|
|
92
96
|
```bash
|
@@ -4,14 +4,24 @@ module Caoutsearch
|
|
4
4
|
module Search
|
5
5
|
module Batch
|
6
6
|
module SearchAfter
|
7
|
-
def search_after(keep_alive:
|
8
|
-
|
7
|
+
def search_after(pit: nil, keep_alive: nil, batch_size: 1000, &block)
|
8
|
+
if pit
|
9
|
+
external_pit = true
|
10
|
+
|
11
|
+
warn(<<~MESSAGE) if keep_alive.nil?
|
12
|
+
A `pit` was passed to batch records without a `keep_alive` argument.
|
13
|
+
You may need it to extend the PIT on each request.
|
14
|
+
MESSAGE
|
15
|
+
end
|
16
|
+
|
17
|
+
keep_alive ||= "1m"
|
18
|
+
pit ||= open_point_in_time(keep_alive: keep_alive)
|
9
19
|
search = per(batch_size).track_total_hits
|
10
20
|
|
11
21
|
request_payload = {
|
12
22
|
body: search.build.to_h.merge(
|
13
23
|
pit: {
|
14
|
-
id:
|
24
|
+
id: pit,
|
15
25
|
keep_alive: keep_alive
|
16
26
|
}
|
17
27
|
)
|
@@ -26,7 +36,7 @@ module Caoutsearch
|
|
26
36
|
loop do
|
27
37
|
requested_at = Time.current
|
28
38
|
|
29
|
-
results = instrument(:search_after, pit:
|
39
|
+
results = instrument(:search_after, pit: pit) do |event_payload|
|
30
40
|
response = client.search(request_payload)
|
31
41
|
last_response_time = Time.current
|
32
42
|
|
@@ -40,27 +50,37 @@ module Caoutsearch
|
|
40
50
|
|
41
51
|
response
|
42
52
|
rescue Elastic::Transport::Transport::Errors::NotFound => e
|
43
|
-
|
53
|
+
if external_pit && progress.zero?
|
54
|
+
raise_enhance_message_on_missing_pit(e)
|
55
|
+
else
|
56
|
+
raise_enhance_message_on_pit_failure(e, keep_alive, requested_at, last_response_time)
|
57
|
+
end
|
44
58
|
end
|
45
59
|
|
46
60
|
hits = results["hits"]["hits"]
|
47
|
-
|
61
|
+
pit = results["pit_id"]
|
48
62
|
break if hits.empty?
|
49
63
|
|
50
64
|
yield hits
|
51
65
|
break if progress >= total
|
52
66
|
|
53
67
|
request_payload[:body].tap do |body|
|
54
|
-
body[:pit][:id] =
|
68
|
+
body[:pit][:id] = pit
|
55
69
|
body[:search_after] = hits.last["sort"]
|
56
70
|
body.delete(:track_total_hits)
|
57
71
|
end
|
58
72
|
end
|
59
73
|
ensure
|
60
|
-
close_point_in_time(
|
74
|
+
close_point_in_time(pit) if pit && !external_pit
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def raise_enhance_message_on_missing_pit(error)
|
80
|
+
raise error.exception "PIT was not found. #{error.message}"
|
61
81
|
end
|
62
82
|
|
63
|
-
def
|
83
|
+
def raise_enhance_message_on_pit_failure(error, keep_alive, requested_at, last_response_time)
|
64
84
|
elapsed = (requested_at - last_response_time).round(1).seconds
|
65
85
|
|
66
86
|
raise error.exception("PIT registered for #{keep_alive}, #{elapsed.inspect} elapsed between. #{error.message}")
|
@@ -7,26 +7,13 @@ module Caoutsearch
|
|
7
7
|
module Testing
|
8
8
|
module MockRequests
|
9
9
|
def stub_elasticsearch_request(verb, pattern)
|
10
|
-
|
11
|
-
host = transport.__full_url(transport.hosts[0])
|
12
|
-
|
13
|
-
# Elasticsearch::Client is verify the connection
|
14
|
-
#
|
15
|
-
unless @subbed_verify
|
16
|
-
root_url = URI.join(host, "/").to_s
|
17
|
-
body = +MultiJson.dump({version: {number: "8.4.1"}})
|
18
|
-
@subbed_verify = stub_request(:get, root_url).to_return(
|
19
|
-
headers: {"Content-Type" => "application/json", "X-Elastic-Product" => "Elasticsearch"},
|
20
|
-
status: 200,
|
21
|
-
body: body
|
22
|
-
)
|
23
|
-
end
|
10
|
+
stub_elasticsearch_validation_request
|
24
11
|
|
25
12
|
case pattern
|
26
13
|
when String
|
27
|
-
pattern = URI.join(
|
14
|
+
pattern = URI.join(elasticsearch_client_host, pattern).to_s
|
28
15
|
when Regexp
|
29
|
-
pattern = URI.join(
|
16
|
+
pattern = URI.join(elasticsearch_client_host, pattern.source).to_s
|
30
17
|
pattern = Regexp.new(pattern)
|
31
18
|
else
|
32
19
|
raise TypeError, "wrong type received for URL pattern"
|
@@ -100,6 +87,45 @@ module Caoutsearch
|
|
100
87
|
|
101
88
|
search_request
|
102
89
|
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def elasticsearch_client_host
|
94
|
+
@client_host ||= begin
|
95
|
+
transport = Caoutsearch.client.transport
|
96
|
+
transport.__full_url(transport.hosts[0])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Elasticsearch::Client is verifying the connection to ES when calling
|
101
|
+
# the first request on the client.
|
102
|
+
#
|
103
|
+
# Prior to version 8.9, it sent a request to "/" before the first request
|
104
|
+
# and match the the "X-Elastic-Product" header and version returned.
|
105
|
+
#
|
106
|
+
# Since 8.9, it matches only the header on the first emitted request.
|
107
|
+
# Because we cannot we cannot edit all the responses headers configured
|
108
|
+
# after calling `stub_elasticsearch_request`, we better have to
|
109
|
+
# call the stubbed request to '/' before any request.
|
110
|
+
#
|
111
|
+
def stub_elasticsearch_validation_request
|
112
|
+
@stubbed_elasticsearch_validation_request ||= begin
|
113
|
+
root_url = URI.join(elasticsearch_client_host, "/").to_s
|
114
|
+
body = +MultiJson.dump({version: {number: Elasticsearch::VERSION}})
|
115
|
+
|
116
|
+
stubbed_request = stub_request(:get, root_url).to_return(
|
117
|
+
headers: {"Content-Type" => "application/json", "X-Elastic-Product" => "Elasticsearch"},
|
118
|
+
status: 200,
|
119
|
+
body: body
|
120
|
+
)
|
121
|
+
|
122
|
+
if Gem::Version.new(Elasticsearch::VERSION) >= Gem::Version.new("8.9.0")
|
123
|
+
Caoutsearch.client.perform_request("GET", "/")
|
124
|
+
end
|
125
|
+
|
126
|
+
stubbed_request
|
127
|
+
end
|
128
|
+
end
|
103
129
|
end
|
104
130
|
end
|
105
131
|
end
|
data/lib/caoutsearch/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caoutsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Savater Sebastien
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-08-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -81,6 +81,216 @@ dependencies:
|
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '2.6'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: activerecord
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: amazing_print
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: appraisal
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: database_cleaner-active_record
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: rake
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: rspec
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
type: :development
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: rubocop
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
type: :development
|
176
|
+
prerelease: false
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
- !ruby/object:Gem::Dependency
|
183
|
+
name: rubocop-rake
|
184
|
+
requirement: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - ">="
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: '0'
|
189
|
+
type: :development
|
190
|
+
prerelease: false
|
191
|
+
version_requirements: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - ">="
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: '0'
|
196
|
+
- !ruby/object:Gem::Dependency
|
197
|
+
name: rubocop-rspec
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
203
|
+
type: :development
|
204
|
+
prerelease: false
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - ">="
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0'
|
210
|
+
- !ruby/object:Gem::Dependency
|
211
|
+
name: rubocop-performance
|
212
|
+
requirement: !ruby/object:Gem::Requirement
|
213
|
+
requirements:
|
214
|
+
- - ">="
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: '0'
|
217
|
+
type: :development
|
218
|
+
prerelease: false
|
219
|
+
version_requirements: !ruby/object:Gem::Requirement
|
220
|
+
requirements:
|
221
|
+
- - ">="
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: '0'
|
224
|
+
- !ruby/object:Gem::Dependency
|
225
|
+
name: simplecov
|
226
|
+
requirement: !ruby/object:Gem::Requirement
|
227
|
+
requirements:
|
228
|
+
- - ">="
|
229
|
+
- !ruby/object:Gem::Version
|
230
|
+
version: '0'
|
231
|
+
type: :development
|
232
|
+
prerelease: false
|
233
|
+
version_requirements: !ruby/object:Gem::Requirement
|
234
|
+
requirements:
|
235
|
+
- - ">="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
- !ruby/object:Gem::Dependency
|
239
|
+
name: standard
|
240
|
+
requirement: !ruby/object:Gem::Requirement
|
241
|
+
requirements:
|
242
|
+
- - ">="
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '1.0'
|
245
|
+
type: :development
|
246
|
+
prerelease: false
|
247
|
+
version_requirements: !ruby/object:Gem::Requirement
|
248
|
+
requirements:
|
249
|
+
- - ">="
|
250
|
+
- !ruby/object:Gem::Version
|
251
|
+
version: '1.0'
|
252
|
+
- !ruby/object:Gem::Dependency
|
253
|
+
name: sqlite3
|
254
|
+
requirement: !ruby/object:Gem::Requirement
|
255
|
+
requirements:
|
256
|
+
- - ">="
|
257
|
+
- !ruby/object:Gem::Version
|
258
|
+
version: '0'
|
259
|
+
type: :development
|
260
|
+
prerelease: false
|
261
|
+
version_requirements: !ruby/object:Gem::Requirement
|
262
|
+
requirements:
|
263
|
+
- - ">="
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: '0'
|
266
|
+
- !ruby/object:Gem::Dependency
|
267
|
+
name: timecop
|
268
|
+
requirement: !ruby/object:Gem::Requirement
|
269
|
+
requirements:
|
270
|
+
- - ">="
|
271
|
+
- !ruby/object:Gem::Version
|
272
|
+
version: '0'
|
273
|
+
type: :development
|
274
|
+
prerelease: false
|
275
|
+
version_requirements: !ruby/object:Gem::Requirement
|
276
|
+
requirements:
|
277
|
+
- - ">="
|
278
|
+
- !ruby/object:Gem::Version
|
279
|
+
version: '0'
|
280
|
+
- !ruby/object:Gem::Dependency
|
281
|
+
name: webmock
|
282
|
+
requirement: !ruby/object:Gem::Requirement
|
283
|
+
requirements:
|
284
|
+
- - ">="
|
285
|
+
- !ruby/object:Gem::Version
|
286
|
+
version: '0'
|
287
|
+
type: :development
|
288
|
+
prerelease: false
|
289
|
+
version_requirements: !ruby/object:Gem::Requirement
|
290
|
+
requirements:
|
291
|
+
- - ">="
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '0'
|
84
294
|
description:
|
85
295
|
email: github.60k5k@simplelogin.co
|
86
296
|
executables: []
|