meilisearch 0.17.3 → 0.18.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c90df98b1b08039b339c49b47bfd052639e1301e9e7e3b25989b9ce6e3d1e67
4
- data.tar.gz: 3f200a9de09db7a47780b01aa20a8ce5b2b1d0d0579954cd8842cb208b06b4dc
3
+ metadata.gz: 9b69f3c0d8bf43393b59abe4e44aabf40ff673dd08bde8f6e60d1c996be8b7bf
4
+ data.tar.gz: d2ff90fe7e1cf738dc4e3297cf7e7215e80c7a63317d06144681fab39206d1b2
5
5
  SHA512:
6
- metadata.gz: b3b38312517176303e9fdc49af5c38647ea4d719d8988cb1e1fd60839e7c593226fd9369febd24a326d214dbb606acd201464fd6590f46438383cf25f3e7e934
7
- data.tar.gz: 494fa30322be3d624851117e460c31046c51ea3ef4d00326f4be969a76f5f056a15147c065b1ef02a56f3a589643e137ac4af1a05a088bab606cdf6d31bc8abc
6
+ metadata.gz: 59dfc2b7ced1fec8a75c32b4b02b49d42a8a63af862bcb86931692be8e9c92b89657b93958c150937ddbe295d645eff5192a181ef439885462c2f6174c1519c3
7
+ data.tar.gz: 71b81d762f8c609a7e2d50ac0052e6c8e0b904c28b2cb7b98f0c55934122c97c1160a4c0b4a2659adcf474a59be85ea609a75183e69550ca4971d177afb8e2b0
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  <p align="center">
2
- <img src="https://res.cloudinary.com/meilisearch/image/upload/v1587402338/SDKs/meilisearch_ruby.svg" alt="MeiliSearch-Ruby" width="200" height="200" />
2
+ <img src="https://raw.githubusercontent.com/meilisearch/integration-guides/main/assets/logos/meilisearch_ruby.svg" alt="Meilisearch-Ruby" width="200" height="200" />
3
3
  </p>
4
4
 
5
- <h1 align="center">MeiliSearch Ruby</h1>
5
+ <h1 align="center">Meilisearch Ruby</h1>
6
6
 
7
7
  <h4 align="center">
8
- <a href="https://github.com/meilisearch/MeiliSearch">MeiliSearch</a> |
8
+ <a href="https://github.com/meilisearch/meilisearch">Meilisearch</a> |
9
9
  <a href="https://docs.meilisearch.com">Documentation</a> |
10
10
  <a href="https://slack.meilisearch.com">Slack</a> |
11
11
  <a href="https://roadmap.meilisearch.com/tabs/1-under-consideration">Roadmap</a> |
@@ -17,21 +17,21 @@
17
17
  <a href="https://badge.fury.io/rb/meilisearch"><img src="https://badge.fury.io/rb/meilisearch.svg" alt="Latest Stable Version"></a>
18
18
  <a href="https://github.com/meilisearch/meilisearch-ruby/actions"><img src="https://github.com/meilisearch/meilisearch-ruby/workflows/Tests/badge.svg" alt="Test"></a>
19
19
  <a href="https://github.com/meilisearch/meilisearch-ruby/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-informational" alt="License"></a>
20
- <a href="https://app.bors.tech/repositories/28781"><img src="https://bors.tech/images/badge_small.svg" alt="Bors enabled"></a>
20
+ <a href="https://ms-bors.herokuapp.com/repositories/6"><img src="https://bors.tech/images/badge_small.svg" alt="Bors enabled"></a>
21
21
  </p>
22
22
 
23
- <p align="center">⚡ The MeiliSearch API client written for Ruby 💎</p>
23
+ <p align="center">⚡ The Meilisearch API client written for Ruby 💎</p>
24
24
 
25
- **MeiliSearch Ruby** is the MeiliSearch API client for Ruby developers.
25
+ **Meilisearch Ruby** is the Meilisearch API client for Ruby developers.
26
26
 
27
- **MeiliSearch** is an open-source search engine. [Discover what MeiliSearch is!](https://github.com/meilisearch/MeiliSearch)
27
+ **Meilisearch** is an open-source search engine. [Discover what Meilisearch is!](https://github.com/meilisearch/meilisearch)
28
28
 
29
29
  ## Table of Contents <!-- omit in toc -->
30
30
 
31
31
  - [📖 Documentation](#-documentation)
32
32
  - [🔧 Installation](#-installation)
33
33
  - [🚀 Getting Started](#-getting-started)
34
- - [🤖 Compatibility with MeiliSearch](#-compatibility-with-meilisearch)
34
+ - [🤖 Compatibility with Meilisearch](#-compatibility-with-meilisearch)
35
35
  - [💡 Learn More](#-learn-more)
36
36
  - [⚙️ Development Workflow and Contributing](#️-development-workflow-and-contributing)
37
37
 
@@ -55,21 +55,21 @@ source 'https://rubygems.org'
55
55
  gem 'meilisearch'
56
56
  ```
57
57
 
58
- ### Run MeiliSearch <!-- omit in toc -->
58
+ ### Run Meilisearch <!-- omit in toc -->
59
59
 
60
- There are many easy ways to [download and run a MeiliSearch instance](https://docs.meilisearch.com/reference/features/installation.html#download-and-launch).
60
+ There are many easy ways to [download and run a Meilisearch instance](https://docs.meilisearch.com/reference/features/installation.html#download-and-launch).
61
61
 
62
62
  For example, using the `curl` command in your [Terminal](https://itconnect.uw.edu/learn/workshops/online-tutorials/web-publishing/what-is-a-terminal/):
63
63
 
64
64
  ```sh
65
- #Install MeiliSearch
65
+ #Install Meilisearch
66
66
  curl -L https://install.meilisearch.com | sh
67
67
 
68
- # Launch MeiliSearch
68
+ # Launch Meilisearch
69
69
  ./meilisearch --master-key=masterKey
70
70
  ```
71
71
 
72
- NB: you can also download MeiliSearch from **Homebrew** or **APT** or even run it using **Docker**.
72
+ NB: you can also download Meilisearch from **Homebrew** or **APT** or even run it using **Docker**.
73
73
 
74
74
  ## 🚀 Getting Started
75
75
 
@@ -91,18 +91,18 @@ documents = [
91
91
  { id: 5, title: 'Moana', genres: ['Fantasy', 'Action']},
92
92
  { id: 6, title: 'Philadelphia', genres: ['Drama'] },
93
93
  ]
94
- # If the index 'movies' does not exist, MeiliSearch creates it when you first add the documents.
95
- index.add_documents(documents) # => { "updateId": 0 }
94
+ # If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
95
+ index.add_documents(documents) # => { "uid": 0 }
96
96
  ```
97
97
 
98
- With the `updateId`, you can check the status (`enqueued`, `processing`, `processed` or `failed`) of your documents addition using the [update endpoint](https://docs.meilisearch.com/reference/api/updates.html#get-an-update-status).
98
+ With the `uid`, you can check the status (`enqueued`, `processing`, `succeeded` or `failed`) of your documents addition using the [task](https://docs.meilisearch.com/reference/api/tasks.html#get-task).
99
99
 
100
100
  💡 To customize the `Client`, for example, increasing the default timeout, please check out [this section](https://github.com/meilisearch/meilisearch-ruby/wiki/Client-Options) of the Wiki.
101
101
 
102
102
  #### Basic Search <!-- omit in toc -->
103
103
 
104
104
  ``` ruby
105
- # MeiliSearch is typo-tolerant:
105
+ # Meilisearch is typo-tolerant:
106
106
  puts index.search('carlo')
107
107
  ```
108
108
  Output:
@@ -165,7 +165,7 @@ index.update_filterable_attributes([
165
165
 
166
166
  You only need to perform this operation once.
167
167
 
168
- Note that MeiliSearch will rebuild your index whenever you update `filterableAttributes`. Depending on the size of your dataset, this might take time. You can track the process using the [update status](https://docs.meilisearch.com/reference/api/updates.html#get-an-update-status).
168
+ Note that Meilisearch will rebuild your index whenever you update `filterableAttributes`. Depending on the size of your dataset, this might take time. You can track the process using the [tasks](https://docs.meilisearch.com/reference/api/tasks.html#get-task)).
169
169
 
170
170
  Then, you can perform the search:
171
171
 
@@ -196,9 +196,9 @@ JSON output:
196
196
  }
197
197
  ```
198
198
 
199
- ## 🤖 Compatibility with MeiliSearch
199
+ ## 🤖 Compatibility with Meilisearch
200
200
 
201
- This package only guarantees the compatibility with the [version v0.24.0 of MeiliSearch](https://github.com/meilisearch/MeiliSearch/releases/tag/v0.24.0).
201
+ This package only guarantees the compatibility with the [version v0.26.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.26.0).
202
202
 
203
203
  ## 💡 Learn More
204
204
 
@@ -219,4 +219,4 @@ If you want to know more about the development workflow or want to contribute, p
219
219
 
220
220
  <hr>
221
221
 
222
- **MeiliSearch** provides and maintains many **SDKs and Integration tools** like this one. We want to provide everyone with an **amazing search experience for any kind of project**. If you want to contribute, make suggestions, or just know what's going on right now, visit us in the [integration-guides](https://github.com/meilisearch/integration-guides) repository.
222
+ **Meilisearch** provides and maintains many **SDKs and Integration tools** like this one. We want to provide everyone with an **amazing search experience for any kind of project**. If you want to contribute, make suggestions, or just know what's going on right now, visit us in the [integration-guides](https://github.com/meilisearch/integration-guides) repository.
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'meilisearch/http_request'
4
-
5
3
  module MeiliSearch
6
4
  class Client < HTTPRequest
5
+ include MeiliSearch::TenantToken
6
+
7
7
  ### INDEXES
8
8
 
9
9
  def raw_indexes
@@ -22,36 +22,20 @@ module MeiliSearch
22
22
  def create_index(index_uid, options = {})
23
23
  body = Utils.transform_attributes(options.merge(uid: index_uid))
24
24
 
25
- index_hash = http_post '/indexes', body
26
- index_object(index_hash['uid'], index_hash['primaryKey'])
25
+ http_post '/indexes', body
27
26
  end
28
27
 
29
- def get_or_create_index(index_uid, options = {})
30
- begin
31
- index_instance = fetch_index(index_uid)
32
- rescue ApiError => e
33
- raise e unless e.code == 'index_not_found'
34
-
35
- index_instance = create_index(index_uid, options)
36
- end
37
- index_instance
28
+ # Synchronous version of create_index.
29
+ # Waits for the task to be achieved, be careful when using it.
30
+ def create_index!(index_uid, options = {})
31
+ task = create_index(index_uid, options)
32
+ wait_for_task(task['uid'])
38
33
  end
39
34
 
40
35
  def delete_index(index_uid)
41
36
  index_object(index_uid).delete
42
37
  end
43
38
 
44
- # Usage:
45
- # client.delete_index_if_exists('indexUID')
46
- def delete_index_if_exists(index_uid)
47
- index_object(index_uid).delete
48
- true
49
- rescue ApiError => e
50
- raise e if e.code != 'index_not_found'
51
-
52
- false
53
- end
54
-
55
39
  # Usage:
56
40
  # client.index('indexUID')
57
41
  def index(index_uid)
@@ -71,7 +55,26 @@ module MeiliSearch
71
55
  def keys
72
56
  http_get '/keys'
73
57
  end
74
- alias get_keys keys
58
+
59
+ def key(key_uid)
60
+ http_get "/keys/#{key_uid}"
61
+ end
62
+
63
+ def create_key(key_options)
64
+ body = Utils.transform_attributes(key_options)
65
+
66
+ http_post '/keys', body
67
+ end
68
+
69
+ def update_key(key_uid, key_options)
70
+ body = Utils.transform_attributes(key_options)
71
+
72
+ http_patch "/keys/#{key_uid}", body
73
+ end
74
+
75
+ def delete_key(key_uid)
76
+ http_delete "/keys/#{key_uid}"
77
+ end
75
78
 
76
79
  ### HEALTH
77
80
 
@@ -107,10 +110,28 @@ module MeiliSearch
107
110
  end
108
111
  alias get_dump_status dump_status
109
112
 
113
+ ### TASKS
114
+
115
+ def tasks
116
+ task_endpoint.task_list
117
+ end
118
+
119
+ def task(task_uid)
120
+ task_endpoint.task(task_uid)
121
+ end
122
+
123
+ def wait_for_task(task_uid, timeout_in_ms = 5000, interval_in_ms = 50)
124
+ task_endpoint.wait_for_task(task_uid, timeout_in_ms, interval_in_ms)
125
+ end
126
+
110
127
  private
111
128
 
112
129
  def index_object(uid, primary_key = nil)
113
130
  Index.new(uid, @base_url, @api_key, primary_key, @options)
114
131
  end
132
+
133
+ def task_endpoint
134
+ @task_endpoint ||= Task.new(@base_url, @api_key, @options)
135
+ end
115
136
  end
116
137
  end
@@ -62,4 +62,10 @@ module MeiliSearch
62
62
  super(@message)
63
63
  end
64
64
  end
65
+
66
+ module TenantToken
67
+ class ExpireOrInvalidSignature < StandardError; end
68
+ class InvalidApiKey < StandardError; end
69
+ class InvalidSearchRules < StandardError; end
70
+ end
65
71
  end
@@ -7,25 +7,30 @@ module MeiliSearch
7
7
  class HTTPRequest
8
8
  include HTTParty
9
9
 
10
- attr_reader :options
10
+ attr_reader :options, :headers
11
+
12
+ DEFAULT_OPTIONS = {
13
+ timeout: 1,
14
+ max_retries: 0,
15
+ convert_body?: true
16
+ }.freeze
11
17
 
12
18
  def initialize(url, api_key = nil, options = {})
13
19
  @base_url = url
14
20
  @api_key = api_key
15
- @options = merge_options({
16
- timeout: 1,
17
- max_retries: 0,
18
- headers: build_default_options_headers(api_key),
19
- convert_body?: true
20
- }, options)
21
+ @options = DEFAULT_OPTIONS.merge(options)
22
+ @headers = build_default_options_headers
21
23
  end
22
24
 
23
25
  def http_get(relative_path = '', query_params = {})
24
26
  send_request(
25
27
  proc { |path, config| self.class.get(path, config) },
26
28
  relative_path,
27
- query_params: query_params,
28
- options: remove_options_header(@options, 'Content-Type')
29
+ config: {
30
+ query_params: query_params,
31
+ headers: remove_headers(@headers.dup, 'Content-Type'),
32
+ options: @options
33
+ }
29
34
  )
30
35
  end
31
36
 
@@ -33,9 +38,12 @@ module MeiliSearch
33
38
  send_request(
34
39
  proc { |path, config| self.class.post(path, config) },
35
40
  relative_path,
36
- query_params: query_params,
37
- body: body,
38
- options: merge_options(@options, options)
41
+ config: {
42
+ query_params: query_params,
43
+ body: body,
44
+ headers: @headers.dup.merge(options[:headers] || {}),
45
+ options: @options.merge(options)
46
+ }
39
47
  )
40
48
  end
41
49
 
@@ -43,9 +51,25 @@ module MeiliSearch
43
51
  send_request(
44
52
  proc { |path, config| self.class.put(path, config) },
45
53
  relative_path,
46
- query_params: query_params,
47
- body: body,
48
- options: @options
54
+ config: {
55
+ query_params: query_params,
56
+ body: body,
57
+ headers: @headers,
58
+ options: @options
59
+ }
60
+ )
61
+ end
62
+
63
+ def http_patch(relative_path = '', body = nil, query_params = nil)
64
+ send_request(
65
+ proc { |path, config| self.class.patch(path, config) },
66
+ relative_path,
67
+ config: {
68
+ query_params: query_params,
69
+ body: body,
70
+ headers: @headers,
71
+ options: @options
72
+ }
49
73
  )
50
74
  end
51
75
 
@@ -53,52 +77,43 @@ module MeiliSearch
53
77
  send_request(
54
78
  proc { |path, config| self.class.delete(path, config) },
55
79
  relative_path,
56
- options: remove_options_header(@options, 'Content-Type')
80
+ config: {
81
+ headers: remove_headers(@headers.dup, 'Content-Type'),
82
+ options: @options
83
+ }
57
84
  )
58
85
  end
59
86
 
60
87
  private
61
88
 
62
- def build_default_options_headers(api_key = nil)
89
+ def build_default_options_headers
63
90
  {
64
91
  'Content-Type' => 'application/json',
65
- 'X-Meili-API-Key' => api_key
92
+ 'Authorization' => ("Bearer #{@api_key}" unless @api_key.nil?),
93
+ 'User-Agent' => MeiliSearch.qualified_version
66
94
  }.compact
67
95
  end
68
96
 
69
- def merge_options(default_options, added_options = {})
70
- default_cloned_headers = default_options[:headers].clone
71
- merged_options = default_options.merge(added_options)
72
- merged_options[:headers] = default_cloned_headers.merge(added_options[:headers]) if added_options.key?(:headers)
73
- merged_options
74
- end
75
-
76
- def remove_options_header(options, key)
77
- cloned_options = clone_options(options)
78
- cloned_options[:headers].tap { |headers| headers.delete(key) }
79
- cloned_options
97
+ def remove_headers(data, *keys)
98
+ data.delete_if { |k| keys.include?(k) }
80
99
  end
81
100
 
82
- def clone_options(options)
83
- cloned_options = options.clone
84
- cloned_options[:headers] = options[:headers].clone
85
- cloned_options
86
- end
101
+ def send_request(http_method, relative_path, config: {})
102
+ config = http_config(config[:query_params], config[:body], config[:options], config[:headers])
87
103
 
88
- def send_request(http_method, relative_path, query_params: nil, body: nil, options: {})
89
- config = http_config(query_params, body, options)
90
104
  begin
91
105
  response = http_method.call(@base_url + relative_path, config)
92
106
  rescue Errno::ECONNREFUSED => e
93
107
  raise CommunicationError, e.message
94
108
  end
109
+
95
110
  validate(response)
96
111
  end
97
112
 
98
- def http_config(query_params, body, options)
113
+ def http_config(query_params, body, options, headers)
99
114
  body = body.to_json if options[:convert_body?] == true
100
115
  {
101
- headers: options[:headers],
116
+ headers: headers,
102
117
  query: query_params,
103
118
  body: body,
104
119
  timeout: options[:timeout],
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'meilisearch/http_request'
4
- require 'timeout'
5
4
 
6
5
  module MeiliSearch
7
6
  class Index < HTTPRequest
@@ -31,10 +30,7 @@ module MeiliSearch
31
30
  end
32
31
 
33
32
  def update(body)
34
- index_hash = http_put indexes_path(id: @uid), Utils.transform_attributes(body)
35
- set_base_properties index_hash
36
-
37
- self
33
+ http_put indexes_path(id: @uid), Utils.transform_attributes(body)
38
34
  end
39
35
 
40
36
  alias update_index update
@@ -78,14 +74,14 @@ module MeiliSearch
78
74
  alias add_or_replace_documents add_documents
79
75
 
80
76
  def add_documents!(documents, primary_key = nil)
81
- update = add_documents(documents, primary_key)
82
- wait_for_pending_update(update['updateId'])
77
+ task = add_documents(documents, primary_key)
78
+ wait_for_task(task['uid'])
83
79
  end
84
80
  alias replace_documents! add_documents!
85
81
  alias add_or_replace_documents! add_documents!
86
82
 
87
83
  def add_documents_json(documents, primary_key = nil)
88
- options = { headers: { 'Content-Type' => 'application/json' }, convert_body?: false }
84
+ options = { convert_body?: false }
89
85
  http_post "/indexes/#{@uid}/documents", documents, { primaryKey: primary_key }.compact, options
90
86
  end
91
87
  alias replace_documents_json add_documents_json
@@ -112,41 +108,41 @@ module MeiliSearch
112
108
  alias add_or_update_documents update_documents
113
109
 
114
110
  def update_documents!(documents, primary_key = nil)
115
- update = update_documents(documents, primary_key)
116
- wait_for_pending_update(update['updateId'])
111
+ task = update_documents(documents, primary_key)
112
+ wait_for_task(task['uid'])
117
113
  end
118
114
  alias add_or_update_documents! update_documents!
119
115
 
120
116
  def add_documents_in_batches(documents, batch_size = 1000, primary_key = nil)
121
- update_ids = []
117
+ tasks = []
122
118
  documents.each_slice(batch_size) do |batch|
123
- update_ids.append(add_documents(batch, primary_key))
119
+ tasks.append(add_documents(batch, primary_key))
124
120
  end
125
- update_ids
121
+ tasks
126
122
  end
127
123
 
128
124
  def add_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
129
- update_ids = add_documents_in_batches(documents, batch_size, primary_key)
125
+ tasks = add_documents_in_batches(documents, batch_size, primary_key)
130
126
  responses = []
131
- update_ids.each do |update_object|
132
- responses.append(wait_for_pending_update(update_object['updateId']))
127
+ tasks.each do |task_obj|
128
+ responses.append(wait_for_task(task_obj['uid']))
133
129
  end
134
130
  responses
135
131
  end
136
132
 
137
133
  def update_documents_in_batches(documents, batch_size = 1000, primary_key = nil)
138
- update_ids = []
134
+ tasks = []
139
135
  documents.each_slice(batch_size) do |batch|
140
- update_ids.append(update_documents(batch, primary_key))
136
+ tasks.append(update_documents(batch, primary_key))
141
137
  end
142
- update_ids
138
+ tasks
143
139
  end
144
140
 
145
141
  def update_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
146
- update_ids = update_documents_in_batches(documents, batch_size, primary_key)
142
+ tasks = update_documents_in_batches(documents, batch_size, primary_key)
147
143
  responses = []
148
- update_ids.each do |update_object|
149
- responses.append(wait_for_pending_update(update_object['updateId']))
144
+ tasks.each do |task_obj|
145
+ responses.append(wait_for_task(task_obj['uid']))
150
146
  end
151
147
  responses
152
148
  end
@@ -161,8 +157,8 @@ module MeiliSearch
161
157
  alias delete_multiple_documents delete_documents
162
158
 
163
159
  def delete_documents!(documents_ids)
164
- update = delete_documents(documents_ids)
165
- wait_for_pending_update(update['updateId'])
160
+ task = delete_documents(documents_ids)
161
+ wait_for_task(task['uid'])
166
162
  end
167
163
  alias delete_multiple_documents! delete_documents!
168
164
 
@@ -173,8 +169,8 @@ module MeiliSearch
173
169
  alias delete_one_document delete_document
174
170
 
175
171
  def delete_document!(document_id)
176
- update = delete_document(document_id)
177
- wait_for_pending_update(update['updateId'])
172
+ task = delete_document(document_id)
173
+ wait_for_task(task['uid'])
178
174
  end
179
175
  alias delete_one_document! delete_document!
180
176
 
@@ -183,8 +179,8 @@ module MeiliSearch
183
179
  end
184
180
 
185
181
  def delete_all_documents!
186
- update = delete_all_documents
187
- wait_for_pending_update(update['updateId'])
182
+ task = delete_all_documents
183
+ wait_for_task(task['uid'])
188
184
  end
189
185
 
190
186
  ### SEARCH
@@ -195,31 +191,23 @@ module MeiliSearch
195
191
  http_post "/indexes/#{@uid}/search", parsed_options
196
192
  end
197
193
 
198
- ### UPDATES
194
+ ### TASKS
199
195
 
200
- def get_update_status(update_id)
201
- http_get "/indexes/#{@uid}/updates/#{update_id}"
196
+ def task_endpoint
197
+ @task_endpoint ||= Task.new(@base_url, @api_key, @options)
202
198
  end
199
+ private :task_endpoint
203
200
 
204
- def get_all_update_status
205
- http_get "/indexes/#{@uid}/updates"
201
+ def task(task_uid)
202
+ task_endpoint.index_task(@uid, task_uid)
206
203
  end
207
204
 
208
- def achieved_upate?(update)
209
- update['status'] != 'enqueued' && update['status'] != 'processing'
205
+ def tasks
206
+ task_endpoint.index_tasks(@uid)
210
207
  end
211
208
 
212
- def wait_for_pending_update(update_id, timeout_in_ms = 5000, interval_in_ms = 50)
213
- Timeout.timeout(timeout_in_ms.to_f / 1000) do
214
- loop do
215
- get_update = get_update_status(update_id)
216
- return get_update if achieved_upate?(get_update)
217
-
218
- sleep interval_in_ms.to_f / 1000
219
- end
220
- end
221
- rescue Timeout::Error
222
- raise MeiliSearch::TimeoutError
209
+ def wait_for_task(task_uid, timeout_in_ms = 5000, interval_in_ms = 50)
210
+ task_endpoint.wait_for_task(task_uid, timeout_in_ms, interval_in_ms)
223
211
  end
224
212
 
225
213
  ### STATS
@@ -236,10 +224,6 @@ module MeiliSearch
236
224
  stats['isIndexing']
237
225
  end
238
226
 
239
- def last_update
240
- stats['lastUpdate']
241
- end
242
-
243
227
  def field_distribution
244
228
  stats['fieldDistribution']
245
229
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'meilisearch/http_request'
4
+ require 'timeout'
5
+
6
+ module MeiliSearch
7
+ class Task < HTTPRequest
8
+ def task_list
9
+ http_get '/tasks/'
10
+ end
11
+
12
+ def task(task_uid)
13
+ http_get "/tasks/#{task_uid}"
14
+ end
15
+
16
+ def index_tasks(index_uid)
17
+ http_get "/indexes/#{index_uid}/tasks"
18
+ end
19
+
20
+ def index_task(index_uid, task_uid)
21
+ http_get "/indexes/#{index_uid}/tasks/#{task_uid}"
22
+ end
23
+
24
+ def wait_for_task(task_uid, timeout_in_ms = 5000, interval_in_ms = 50)
25
+ Timeout.timeout(timeout_in_ms.to_f / 1000) do
26
+ loop do
27
+ task = task(task_uid)
28
+ return task if achieved_task?(task)
29
+
30
+ sleep interval_in_ms.to_f / 1000
31
+ end
32
+ end
33
+ rescue Timeout::Error
34
+ raise MeiliSearch::TimeoutError
35
+ end
36
+
37
+ private
38
+
39
+ def achieved_task?(task)
40
+ task['status'] != 'enqueued' && task['status'] != 'processing'
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MeiliSearch
4
+ module TenantToken
5
+ HEADER = {
6
+ typ: 'JWT',
7
+ alg: 'HS256'
8
+ }.freeze
9
+
10
+ def generate_tenant_token(search_rules, api_key: nil, expires_at: nil)
11
+ signature = retrieve_valid_key!(api_key, @api_key)
12
+ expiration = validate_expires_at!(expires_at)
13
+ rules = validate_search_rules!(search_rules)
14
+ unsigned_data = build_payload(expiration, rules, signature)
15
+
16
+ combine(unsigned_data, to_base64(sign_data(signature, unsigned_data)))
17
+ end
18
+
19
+ private
20
+
21
+ def build_payload(expiration, rules, signature)
22
+ payload = {
23
+ searchRules: rules,
24
+ apiKeyPrefix: signature[0..7],
25
+ exp: expiration
26
+ }
27
+
28
+ combine(encode(HEADER), encode(payload))
29
+ end
30
+
31
+ def validate_expires_at!(expires_at)
32
+ return unless expires_at
33
+ return expires_at.to_i if expires_at.utc? && expires_at > Time.now.utc
34
+
35
+ raise
36
+ rescue StandardError
37
+ raise ExpireOrInvalidSignature
38
+ end
39
+
40
+ def validate_search_rules!(data)
41
+ return data if data
42
+
43
+ raise InvalidSearchRules
44
+ end
45
+
46
+ def retrieve_valid_key!(*keys)
47
+ key = keys.compact.find { |k| !k.empty? }
48
+
49
+ raise InvalidApiKey if key.nil?
50
+
51
+ key
52
+ end
53
+
54
+ def sign_data(key, msg)
55
+ OpenSSL::HMAC.digest('SHA256', key, msg)
56
+ end
57
+
58
+ def to_base64(data)
59
+ Base64.urlsafe_encode64(data, padding: false)
60
+ end
61
+
62
+ def encode(data)
63
+ to_base64(JSON.generate(data))
64
+ end
65
+
66
+ def combine(*parts)
67
+ parts.join('.')
68
+ end
69
+ end
70
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MeiliSearch
4
- VERSION = '0.17.3'
4
+ VERSION = '0.18.2'
5
+
6
+ def self.qualified_version
7
+ "Meilisearch Ruby (v#{VERSION})"
8
+ end
5
9
  end
data/lib/meilisearch.rb CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  require 'meilisearch/version'
4
4
  require 'meilisearch/utils'
5
+ require 'meilisearch/http_request'
6
+ require 'meilisearch/tenant_token'
7
+ require 'meilisearch/task'
5
8
  require 'meilisearch/client'
6
9
  require 'meilisearch/index'
7
10
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meilisearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.3
4
+ version: 0.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-13 00:00:00.000000000 Z
11
+ date: 2022-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -30,7 +30,7 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: 0.21.0
33
- description: An easy-to-use ruby client for Meilisearch API. See https://github.com/meilisearch/MeiliSearch
33
+ description: An easy-to-use ruby client for Meilisearch API. See https://github.com/meilisearch/meilisearch
34
34
  email: bonjour@meilisearch.com
35
35
  executables: []
36
36
  extensions: []
@@ -43,6 +43,8 @@ files:
43
43
  - lib/meilisearch/error.rb
44
44
  - lib/meilisearch/http_request.rb
45
45
  - lib/meilisearch/index.rb
46
+ - lib/meilisearch/task.rb
47
+ - lib/meilisearch/tenant_token.rb
46
48
  - lib/meilisearch/utils.rb
47
49
  - lib/meilisearch/version.rb
48
50
  homepage: https://github.com/meilisearch/meilisearch-ruby