algoliasearch 1.4.0 → 1.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60f96e5a2607dcefc2d61bfd860ee85334fc4974
4
- data.tar.gz: 13a0e314c0fb5df77b4189030e6505e76a7f8924
3
+ metadata.gz: d9df8ced9c8a5da4e7e677c2643b24891b84a406
4
+ data.tar.gz: ea2d150a9d5171f5e4da18a6a5c7758137d31aa5
5
5
  SHA512:
6
- metadata.gz: 84e2f40e68e6a1114196025eba308416ddcf6156d4bec2bf99cba69a5d0420d279c0d1294df2200eb07c6dc5d0749d3ff943f1c17f80ed62e707799e20dcb796
7
- data.tar.gz: b2fd8567ef442cd5b987a684fb56a5c83d5b753034a62dffdc551b16a69862ea92d733a95eda3ddf532d2b99105ea8761c48a86e48e8f9fb57a8d58617cef635
6
+ metadata.gz: 04a47d4b5227e7e97db5d33fb1759a3c053e0e34a94fb6d7eb380c97a4ae4dbfc097df30755afa2524f41cc93400d19c2b3db5d70676cd9a5469ba68cadab3e4
7
+ data.tar.gz: 088ba592a94f6e31dd3d0f07f5668b53bb63932fd8680e84c03da0dc7a0add25aaa8a8bfca3f8c9b43ec797d0288391611ec441f89d0bfa77a188de3ffbfdbd8
data/ChangeLog CHANGED
@@ -1,5 +1,8 @@
1
1
  CHANGELOG
2
2
 
3
+ 2015-04-10 1.4.1
4
+ * Force the default connect/read/write/search/batch timeouts to Algolia-specific values
5
+
3
6
  2015-03-17 1.4.0
4
7
  * High-available DNS: search queries are now targeting "APPID-DSN.algolia.net" first, then the main cluster using NSOne, then the main cluster using Route53.
5
8
  Indexing queries are targeting "APPID.algolia.net" first, then the main cluster using NSOne, then the main cluster using Route53.
data/README.md CHANGED
@@ -3,21 +3,8 @@
3
3
 
4
4
 
5
5
  [Algolia Search](http://www.algolia.com) is a hosted full-text, numerical, and faceted search engine capable of delivering realtime results from the first keystroke.
6
- Algolia's Search API makes it easy to deliver a great search experience in your websites and mobile applications by providing:
7
6
 
8
- * REST and JSON based API
9
- * Search against infinite attributes from a single search box
10
- * Instant search as you type experience
11
- * Relevance and popularity ranking
12
- * Global language support
13
- * Typo tolerance in any language
14
- * Smart highlighting
15
- * Facet as you type
16
- * Geo awareness
17
- * 99.99% SLA
18
- * First class data security
19
-
20
- Our Ruby client lets you easily use the [Algolia Search API](http://www.algolia.com) from your backend. It wraps the [Algolia Search REST API](http://www.algolia.com/doc/rest_api).
7
+ Our Ruby client lets you easily use the [Algolia Search API](https://www.algolia.com/doc/rest_api) from your backend. It wraps the [Algolia Search REST API](http://www.algolia.com/doc/rest_api).
21
8
 
22
9
 
23
10
  [![Build Status](https://travis-ci.org/algolia/algoliasearch-client-ruby.svg?branch=master)](https://travis-ci.org/algolia/algoliasearch-client-ruby) [![Gem Version](https://badge.fury.io/rb/algoliasearch.svg)](http://badge.fury.io/rb/algoliasearch) [![Code Climate](https://codeclimate.com/github/algolia/algoliasearch-client-ruby.svg)](https://codeclimate.com/github/algolia/algoliasearch-client-ruby) [![Coverage Status](https://coveralls.io/repos/algolia/algoliasearch-client-ruby/badge.png)](https://coveralls.io/r/algolia/algoliasearch-client-ruby)
@@ -131,25 +118,35 @@ puts index.search('jim').to_json
131
118
 
132
119
  **Notes:** If you are building a web application, you may be more interested in using our [JavaScript client](https://github.com/algolia/algoliasearch-client-js) to perform queries. It brings two benefits:
133
120
  * Your users get a better response time by not going through your servers
134
- * It will offload unnecessary tasks from your servers.
121
+ * It will offload unnecessary tasks from your servers
135
122
 
136
123
  ```html
137
- <script type="text/javascript" src="//path/to/algoliasearch.min.js"></script>
138
- <script type="text/javascript">
139
- var client = new AlgoliaSearch("YourApplicationID", "YourSearchOnlyAPIKey");
140
- var index = client.initIndex('YourIndexName');
141
-
142
- function searchCallback(success, content) {
143
- if (success) {
144
- console.log(content);
145
- }
124
+ <script src="//cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
125
+ <script>
126
+ var client = algoliasearch('ApplicationID', 'Search-Only-API-Key');
127
+ var index = client.initIndex('indexName');
128
+
129
+ // perform query "jim"
130
+ index.search('jim', searchCallback);
131
+
132
+ // the last optional argument can be used to add search parameters
133
+ index.search(
134
+ 'jim', {
135
+ hitsPerPage: 5,
136
+ facets: '*',
137
+ maxValuesPerFacet: 10
138
+ },
139
+ searchCallback
140
+ );
141
+
142
+ function searchCallback(err, content) {
143
+ if (err) {
144
+ console.error(err);
145
+ return;
146
146
  }
147
147
 
148
- // perform query "jim"
149
- index.search("jim", searchCallback);
150
-
151
- // the last optional argument can be used to add search parameters
152
- index.search("jim", searchCallback, { hitsPerPage: 5, facets: '*', maxValuesPerFacet: 10 });
148
+ console.log(content);
149
+ }
153
150
  </script>
154
151
  ```
155
152
 
@@ -390,7 +387,7 @@ res = index.search("query string", { "attributesToRetrieve" => "firstname,lastna
390
387
 
391
388
  The server response will look like:
392
389
 
393
- ```javascript
390
+ ```json
394
391
  {
395
392
  "hits": [
396
393
  {
@@ -458,6 +455,7 @@ res = index.get_object("myID", "fistname")
458
455
 
459
456
  You can also retrieve a set of objects:
460
457
 
458
+
461
459
  ```ruby
462
460
  res = index.get_objects(["myID", "myID2"])
463
461
  ```
@@ -466,6 +464,7 @@ res = index.get_objects(["myID", "myID2"])
466
464
 
467
465
 
468
466
 
467
+
469
468
  Delete an object
470
469
  -------------
471
470
 
@@ -740,15 +739,23 @@ You may have a single index containing per user data. In that case, all records
740
739
  public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', '(public,user_42)'
741
740
  ```
742
741
 
743
- This public API key must then be used in your JavaScript code as follow:
742
+ This public API key can then be used in your JavaScript code as follow:
744
743
 
745
744
  ```javascript
746
745
  <script type="text/javascript">
747
- var algolia = new AlgoliaSearch('YourApplicationID', '<%= public_api_key %>');
748
- algolia.setSecurityTags('(public,user_42)'); // must be same than those used at generation-time
749
- algolia.initIndex('YourIndex').search($('#q').val(), function(success, content) {
750
- // [...]
751
- });
746
+ var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
747
+ client.setSecurityTags('(public,user_42)'); // must be same than those used at generation-time
748
+
749
+ var index = client.initIndex('indexName')
750
+
751
+ index.search('something', function(err, content) {
752
+ if (err) {
753
+ console.error(err);
754
+ return;
755
+ }
756
+
757
+ console.log(content);
758
+ });
752
759
  </script>
753
760
  ```
754
761
 
@@ -761,16 +768,28 @@ You can mix rate limits and secured API keys by setting an extra `user_token` at
761
768
  public_key = Algolia.generate_secured_api_key 'YourRateLimitedApiKey', '(public,user_42)', 'user_42'
762
769
  ```
763
770
 
764
- This public API key must then be used in your JavaScript code as follow:
771
+ This public API key can then be used in your JavaScript code as follow:
765
772
 
766
773
  ```javascript
767
774
  <script type="text/javascript">
768
- var algolia = new AlgoliaSearch('YourApplicationID', '<%= public_api_key %>');
769
- algolia.setSecurityTags('(public,user_42)'); // must be same than those used at generation-time
770
- algolia.setUserToken('user_42') // must be same than the one used at generation-time
771
- algolia.initIndex('YourIndex').search($('#q').val(), function(success, content) {
772
- // [...]
773
- });
775
+ var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
776
+
777
+ // must be same than those used at generation-time
778
+ client.setSecurityTags('(public,user_42)');
779
+
780
+ // must be same than the one used at generation-time
781
+ client.setUserToken('user_42');
782
+
783
+ var index = client.initIndex('indexName')
784
+
785
+ index.search('another query', function(err, content) {
786
+ if (err) {
787
+ console.error(err);
788
+ return;
789
+ }
790
+
791
+ console.log(content);
792
+ });
774
793
  </script>
775
794
  ```
776
795
 
@@ -10,20 +10,26 @@ module Algolia
10
10
  # A class which encapsulates the HTTPS communication with the Algolia
11
11
  # API server. Uses the HTTPClient library for low-level HTTP communication.
12
12
  class Client
13
- attr_reader :ssl, :ssl_version, :hosts, :search_hosts, :application_id, :api_key, :headers, :connect_timeout, :send_timeout, :receive_timeout, :search_timeout
13
+ attr_reader :ssl, :ssl_version, :hosts, :search_hosts, :application_id, :api_key, :headers, :connect_timeout, :send_timeout, :receive_timeout, :search_timeout, :batch_timeout
14
14
 
15
+ DEFAULT_CONNECT_TIMEOUT = 2
16
+ DEFAULT_RECEIVE_TIMEOUT = 30
17
+ DEFAULT_SEND_TIMEOUT = 30
18
+ DEFAULT_BATCH_TIMEOUT = 120
19
+ DEFAULT_SEARCH_TIMEOUT = 5
15
20
 
16
21
  def initialize(data = {})
17
22
  @ssl = data[:ssl].nil? ? true : data[:ssl]
18
23
  @ssl_version = data[:ssl_version].nil? ? nil : data[:ssl_version]
19
24
  @application_id = data[:application_id]
20
25
  @api_key = data[:api_key]
21
- @hosts = data[:hosts] || (["#{@application_id}.algolia.net"] + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolia.net" }.shuffle + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolianet.com" }.shuffle)
22
- @search_hosts = data[:search_hosts] || (["#{@application_id}-dsn.algolia.net"] + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolia.net" }.shuffle + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolianet.com" }.shuffle)
23
- @connect_timeout = data[:connect_timeout]
24
- @send_timeout = data[:send_timeout]
25
- @receive_timeout = data[:receive_timeout]
26
- @search_timeout = data[:search_timeout]
26
+ @hosts = data[:hosts] || (["#{@application_id}.algolia.net"] + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolianet.com" }.shuffle)
27
+ @search_hosts = data[:search_hosts] || data[:hosts] || (["#{@application_id}-dsn.algolia.net"] + 1.upto(3).map { |i| "#{@application_id}-#{i}.algolianet.com" }.shuffle)
28
+ @connect_timeout = data[:connect_timeout] || DEFAULT_CONNECT_TIMEOUT
29
+ @send_timeout = data[:send_timeout] || DEFAULT_SEND_TIMEOUT
30
+ @batch_timeout = data[:batch_timeout] || DEFAULT_BATCH_TIMEOUT
31
+ @receive_timeout = data[:receive_timeout] || DEFAULT_RECEIVE_TIMEOUT
32
+ @search_timeout = data[:search_timeout] || DEFAULT_SEARCH_TIMEOUT
27
33
  @headers = {
28
34
  Protocol::HEADER_API_KEY => api_key,
29
35
  Protocol::HEADER_APP_ID => application_id,
@@ -36,9 +42,26 @@ module Algolia
36
42
  # with common basic response handling. Will raise a
37
43
  # AlgoliaProtocolError if the response has an error status code,
38
44
  # and will return the parsed JSON body on success, if there is one.
39
- def request(uri, method, data = nil, timeout = nil, read = false)
45
+ def request(uri, method, data = nil, type = :write)
40
46
  exceptions = []
41
- thread_local_hosts(read, timeout).each do |host|
47
+
48
+ connect_timeout = @connect_timeout
49
+ send_timeout = if type == :search
50
+ @search_timeout
51
+ elsif type == :batch
52
+ type = :write
53
+ @batch_timeout
54
+ else
55
+ @send_timeout
56
+ end
57
+ receive_timeout = type == :search ? @search_timeout : @receive_timeout
58
+
59
+ (type == :write ? @hosts : @search_hosts).size.times do |i|
60
+ connect_timeout += 2 if i == 2
61
+ send_timeout += 10 if i == 2
62
+ receive_timeout += 10 if i == 2
63
+
64
+ host = thread_local_hosts(type != :write, connect_timeout, send_timeout, receive_timeout)[i]
42
65
  begin
43
66
  return perform_request(host[:session], host[:base_url] + uri, method, data)
44
67
  rescue AlgoliaProtocolError => e
@@ -51,20 +74,20 @@ module Algolia
51
74
  raise AlgoliaProtocolError.new(0, "Cannot reach any host: #{exceptions.map { |e| e.to_s }.join(', ')}")
52
75
  end
53
76
 
54
- def get(uri, timeout = nil, read = false)
55
- request(uri, :GET, nil, timeout, read)
77
+ def get(uri, type = :write)
78
+ request(uri, :GET, nil, type)
56
79
  end
57
80
 
58
- def post(uri, body = {}, timeout = nil, read = false)
59
- request(uri, :POST, body, timeout, read)
81
+ def post(uri, body = {}, type = :write)
82
+ request(uri, :POST, body, type)
60
83
  end
61
84
 
62
- def put(uri, body = {}, timeout = nil, read = false)
63
- request(uri, :PUT, body, timeout, read)
85
+ def put(uri, body = {}, type = :write)
86
+ request(uri, :PUT, body, type)
64
87
  end
65
88
 
66
- def delete(uri, timeout = nil, read = false)
67
- request(uri, :DELETE, nil, timeout, read)
89
+ def delete(uri, type = :write)
90
+ request(uri, :DELETE, nil, type)
68
91
  end
69
92
 
70
93
  private
@@ -75,10 +98,10 @@ module Algolia
75
98
  # if you change any of its attributes, we cannot change the timeout
76
99
  # of an HTTP session dynamically. That being said, having 1 pool per
77
100
  # timeout appears to be the only acceptable solution
78
- def thread_local_hosts(read, forced_timeout)
79
- k = read ? :algolia_search_hosts : :algolia_hosts
80
- Thread.current[k] ||= {}
81
- Thread.current[k][forced_timeout.to_s] ||= (read ? search_hosts : hosts).map do |host|
101
+ def thread_local_hosts(read, connect_timeout, send_timeout, receive_timeout)
102
+ thread_local_var = read ? :algolia_search_hosts : :algolia_hosts
103
+ Thread.current[thread_local_var] ||= {}
104
+ Thread.current[thread_local_var]["#{connect_timeout}-#{send_timeout}-#{receive_timeout}"] ||= (read ? search_hosts : hosts).map do |host|
82
105
  client = HTTPClient.new
83
106
  client.ssl_config.ssl_version = @ssl_version if @ssl && @ssl_version
84
107
  hinfo = {
@@ -86,13 +109,9 @@ module Algolia
86
109
  :session => client
87
110
  }
88
111
  hinfo[:session].transparent_gzip_decompression = true
89
- hinfo[:session].connect_timeout = @connect_timeout if @connect_timeout
90
- if forced_timeout
91
- hinfo[:session].send_timeout = hinfo[:session].receive_timeout = forced_timeout
92
- else
93
- hinfo[:session].send_timeout = @send_timeout if @send_timeout
94
- hinfo[:session].receive_timeout = @receive_timeout if @receive_timeout
95
- end
112
+ hinfo[:session].connect_timeout = connect_timeout
113
+ hinfo[:session].send_timeout = send_timeout
114
+ hinfo[:session].receive_timeout = receive_timeout
96
115
  hinfo[:session].ssl_config.add_trust_ca File.join(File.dirname(__FILE__), '..', '..', 'resources', 'ca-bundle.crt')
97
116
  hinfo
98
117
  end
@@ -210,7 +229,7 @@ module Algolia
210
229
  { :indexName => indexName, :params => Protocol.to_query(encoded_params) }
211
230
  end
212
231
  }
213
- Algolia.client.post(Protocol.multiple_queries_uri, requests.to_json, Algolia.client.search_timeout, true)
232
+ Algolia.client.post(Protocol.multiple_queries_uri, requests.to_json, :search)
214
233
  end
215
234
 
216
235
  #
@@ -220,7 +239,7 @@ module Algolia
220
239
  # {"name": "notes", "createdAt": "2013-01-18T15:33:13.556Z"}]}
221
240
  #
222
241
  def Algolia.list_indexes
223
- Algolia.client.get(Protocol.indexes_uri)
242
+ Algolia.client.get(Protocol.indexes_uri, :read)
224
243
  end
225
244
 
226
245
  #
@@ -296,12 +315,12 @@ module Algolia
296
315
 
297
316
  # List all existing user keys with their associated ACLs
298
317
  def Algolia.list_user_keys
299
- Algolia.client.get(Protocol.keys_uri)
318
+ Algolia.client.get(Protocol.keys_uri, :read)
300
319
  end
301
320
 
302
321
  # Get ACL of a user key
303
322
  def Algolia.get_user_key(key)
304
- Algolia.client.get(Protocol.key_uri(key))
323
+ Algolia.client.get(Protocol.key_uri(key), :read)
305
324
  end
306
325
 
307
326
  #
@@ -136,7 +136,7 @@ module Algolia
136
136
  # one is kept and others are removed.
137
137
  def search(query, params = {})
138
138
  encoded_params = Hash[params.map { |k,v| [k.to_s, v.is_a?(Array) ? v.to_json : v] }]
139
- Algolia.client.get(Protocol.search_uri(name, query, encoded_params), Algolia.client.search_timeout, true)
139
+ Algolia.client.get(Protocol.search_uri(name, query, encoded_params), :search)
140
140
  end
141
141
 
142
142
  #
@@ -147,7 +147,7 @@ module Algolia
147
147
  # @param hitsPerPage: Pagination parameter used to select the number of hits per page. Defaults to 1000.
148
148
  #
149
149
  def browse(page = 0, hitsPerPage = 1000)
150
- Algolia.client.get(Protocol.browse_uri(name, {:page => page, :hitsPerPage => hitsPerPage}))
150
+ Algolia.client.get(Protocol.browse_uri(name, {:page => page, :hitsPerPage => hitsPerPage}), :read)
151
151
  end
152
152
 
153
153
  #
@@ -158,9 +158,9 @@ module Algolia
158
158
  #
159
159
  def get_object(objectID, attributesToRetrieve = nil)
160
160
  if attributesToRetrieve.nil?
161
- Algolia.client.get(Protocol.object_uri(name, objectID, nil), Algolia.client.search_timeout, true)
161
+ Algolia.client.get(Protocol.object_uri(name, objectID, nil), :read)
162
162
  else
163
- Algolia.client.get(Protocol.object_uri(name, objectID, {:attributes => attributesToRetrieve}), Algolia.client.search_timeout, true)
163
+ Algolia.client.get(Protocol.object_uri(name, objectID, {:attributes => attributesToRetrieve}), :read)
164
164
  end
165
165
  end
166
166
 
@@ -170,7 +170,7 @@ module Algolia
170
170
  # @param objectIDs the array of unique identifier of the objects to retrieve
171
171
  #
172
172
  def get_objects(objectIDs)
173
- Algolia.client.post(Protocol.objects_uri, { :requests => objectIDs.map { |objectID| { :indexName => name, :objectID => objectID } } }.to_json, Algolia.client.search_timeout, true)['results']
173
+ Algolia.client.post(Protocol.objects_uri, { :requests => objectIDs.map { |objectID| { :indexName => name, :objectID => objectID } } }.to_json, :read)['results']
174
174
  end
175
175
 
176
176
  # Wait the publication of a task on the server.
@@ -181,7 +181,7 @@ module Algolia
181
181
  #
182
182
  def wait_task(taskID, timeBeforeRetry = 100)
183
183
  loop do
184
- status = Algolia.client.get(Protocol.task_uri(name, taskID), nil, true)["status"]
184
+ status = Algolia.client.get(Protocol.task_uri(name, taskID), :read)["status"]
185
185
  if status == "published"
186
186
  return
187
187
  end
@@ -416,17 +416,17 @@ module Algolia
416
416
 
417
417
  # Get settings of this index
418
418
  def get_settings
419
- Algolia.client.get(Protocol.settings_uri(name))
419
+ Algolia.client.get(Protocol.settings_uri(name), :read)
420
420
  end
421
421
 
422
422
  # List all existing user keys with their associated ACLs
423
423
  def list_user_keys
424
- Algolia.client.get(Protocol.index_keys_uri(name))
424
+ Algolia.client.get(Protocol.index_keys_uri(name), :read)
425
425
  end
426
426
 
427
427
  # Get ACL of a user key
428
428
  def get_user_key(key)
429
- Algolia.client.get(Protocol.index_key_uri(name, key))
429
+ Algolia.client.get(Protocol.index_key_uri(name, key), :read)
430
430
  end
431
431
 
432
432
  #
@@ -473,7 +473,7 @@ module Algolia
473
473
 
474
474
  # Send a batch request
475
475
  def batch(request)
476
- Algolia.client.post(Protocol.batch_uri(name), request.to_json)
476
+ Algolia.client.post(Protocol.batch_uri(name), request.to_json, :batch)
477
477
  end
478
478
 
479
479
  # Send a batch request and wait the end of the indexing
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = "1.4.0"
2
+ VERSION = "1.4.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algoliasearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Algolia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-17 00:00:00.000000000 Z
11
+ date: 2015-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient