elastomer-client 0.7.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.overcommit.yml +5 -0
  3. data/.rubocop.yml +83 -0
  4. data/CHANGELOG.md +8 -0
  5. data/Gemfile +2 -2
  6. data/README.md +1 -1
  7. data/Rakefile +2 -2
  8. data/elastomer-client.gemspec +4 -2
  9. data/lib/elastomer/client.rb +42 -37
  10. data/lib/elastomer/client/bulk.rb +2 -2
  11. data/lib/elastomer/client/cluster.rb +19 -19
  12. data/lib/elastomer/client/delete_by_query.rb +7 -7
  13. data/lib/elastomer/client/docs.rb +81 -24
  14. data/lib/elastomer/client/errors.rb +2 -2
  15. data/lib/elastomer/client/index.rb +65 -29
  16. data/lib/elastomer/client/multi_percolate.rb +127 -0
  17. data/lib/elastomer/client/multi_search.rb +2 -2
  18. data/lib/elastomer/client/nodes.rb +4 -4
  19. data/lib/elastomer/client/percolator.rb +77 -0
  20. data/lib/elastomer/client/repository.rb +7 -7
  21. data/lib/elastomer/client/scroller.rb +14 -14
  22. data/lib/elastomer/client/snapshot.rb +9 -9
  23. data/lib/elastomer/client/template.rb +3 -3
  24. data/lib/elastomer/client/warmer.rb +5 -16
  25. data/lib/elastomer/core_ext/time.rb +1 -1
  26. data/lib/elastomer/middleware/encode_json.rb +5 -5
  27. data/lib/elastomer/middleware/opaque_id.rb +3 -3
  28. data/lib/elastomer/middleware/parse_json.rb +5 -5
  29. data/lib/elastomer/notifications.rb +4 -4
  30. data/lib/elastomer/version.rb +1 -1
  31. data/script/bootstrap +2 -0
  32. data/script/console +5 -5
  33. data/test/assertions.rb +26 -24
  34. data/test/client/bulk_test.rb +111 -111
  35. data/test/client/cluster_test.rb +58 -58
  36. data/test/client/delete_by_query_test.rb +53 -53
  37. data/test/client/docs_test.rb +279 -203
  38. data/test/client/errors_test.rb +1 -1
  39. data/test/client/index_test.rb +143 -109
  40. data/test/client/multi_percolate_test.rb +130 -0
  41. data/test/client/multi_search_test.rb +30 -28
  42. data/test/client/nodes_test.rb +30 -29
  43. data/test/client/percolator_test.rb +52 -0
  44. data/test/client/repository_test.rb +23 -23
  45. data/test/client/scroller_test.rb +40 -40
  46. data/test/client/snapshot_test.rb +15 -15
  47. data/test/client/stubbed_client_test.rb +15 -15
  48. data/test/client/template_test.rb +10 -10
  49. data/test/client/warmer_test.rb +18 -18
  50. data/test/client_test.rb +53 -53
  51. data/test/core_ext/time_test.rb +12 -12
  52. data/test/middleware/encode_json_test.rb +20 -20
  53. data/test/middleware/opaque_id_test.rb +10 -10
  54. data/test/middleware/parse_json_test.rb +14 -14
  55. data/test/notifications_test.rb +32 -32
  56. data/test/test_helper.rb +24 -24
  57. metadata +38 -2
@@ -0,0 +1,127 @@
1
+ module Elastomer
2
+ class Client
3
+
4
+ # Execute an array of percolate actions in bulk. Results are returned in an
5
+ # array in the order the actions were sent.
6
+ #
7
+ # The `multi_percolate` method can be used in two ways. Without a block
8
+ # the method will perform an API call, and it requires a bulk request
9
+ # body and optional request parameters.
10
+ #
11
+ # See https://www.elastic.co/guide/en/elasticsearch/reference/current/search-percolate.html#_multi_percolate_api
12
+ #
13
+ # body - Request body as a String (required if a block is not given)
14
+ # params - Optional request parameters as a Hash
15
+ # block - Passed to a MultiPercolate instance which assembles the
16
+ # percolate actions into a single request.
17
+ #
18
+ # Examples
19
+ #
20
+ # # index and type in request body
21
+ # multi_percolate(request_body)
22
+ #
23
+ # # index in URI
24
+ # multi_percolate(request_body, :index => 'default-index')
25
+ #
26
+ # # block form
27
+ # multi_percolate(:index => 'default-index') do |m|
28
+ # m.percolate({ :author => "pea53" }, { :type => 'default-type' })
29
+ # m.count({ :author => "pea53" }, { :type => 'type2' })
30
+ # ...
31
+ # end
32
+ #
33
+ # Returns the response body as a Hash
34
+ def multi_percolate(body = nil, params = nil)
35
+ if block_given?
36
+ params, body = (body || {}), nil
37
+ yield mpercolate_obj = MultiPercolate.new(self, params)
38
+ mpercolate_obj.call
39
+ else
40
+ raise "multi_percolate request body cannot be nil" if body.nil?
41
+ params ||= {}
42
+
43
+ response = self.post "{/index}{/type}/_mpercolate", params.merge(:body => body)
44
+ response.body
45
+ end
46
+ end
47
+ alias_method :mpercolate, :multi_percolate
48
+
49
+ # The MultiPercolate class is a helper for accumulating and submitting
50
+ # multi_percolate API requests. Instances of the MultiPercolate class
51
+ # accumulate percolate actions and then issue a single API request to
52
+ # Elasticsearch, which runs all accumulated percolate actions in parallel
53
+ # and returns each result hash aggregated into an array of result
54
+ # hashes.
55
+ #
56
+ # Instead of instantiating this class directly, use
57
+ # the block form of Client#multi_percolate.
58
+ #
59
+ class MultiPercolate
60
+
61
+ # Create a new MultiPercolate instance for accumulating percolate actions
62
+ # and submitting them all as a single request.
63
+ #
64
+ # client - Elastomer::Client used for HTTP requests to the server
65
+ # params - Parameters Hash to pass to the Client#multi_percolate method
66
+ def initialize(client, params = {})
67
+ @client = client
68
+ @params = params
69
+
70
+ @actions = []
71
+ end
72
+
73
+ attr_reader :client
74
+
75
+ # Add a percolate action to the multi percolate request. This percolate
76
+ # action will not be executed until the multi_percolate API call is made.
77
+ #
78
+ # header - A Hash of the index and type, if not provided in the params
79
+ # doc - A Hash of the document
80
+ #
81
+ # Returns this MultiPercolate instance.
82
+ def percolate(doc, header = {})
83
+ add_to_actions(:percolate => header)
84
+ add_to_actions(:doc => doc)
85
+ end
86
+
87
+ # Add a percolate acount action to the multi percolate request. This
88
+ # percolate count action will not be executed until the multi_percolate
89
+ # API call is made.
90
+ #
91
+ # header - A Hash of the index and type, if not provided in the params
92
+ # doc - A Hash of the document
93
+ #
94
+ # Returns this MultiPercolate instance.
95
+ def count(doc, header = {})
96
+ add_to_actions(:count => header)
97
+ add_to_actions(:doc => doc)
98
+ end
99
+
100
+ # Execute the multi_percolate call with the accumulated percolate actions.
101
+ # If the accumulated actions list is empty then no action is taken.
102
+ #
103
+ # Returns the response body Hash.
104
+ def call
105
+ return if @actions.empty?
106
+
107
+ body = @actions.join("\n") + "\n"
108
+ client.multi_percolate(body, @params)
109
+ ensure
110
+ @actions.clear
111
+ end
112
+
113
+ # Internal: Add an action to the pending request. Actions can be
114
+ # either headers or bodies. The first action must be a percolate header,
115
+ # followed by a body, then alternating headers and bodies.
116
+ #
117
+ # action - the Hash (header or body) to add to the pending request
118
+ #
119
+ # Returns this MultiPercolate instance.
120
+ def add_to_actions(action)
121
+ action = MultiJson.dump action
122
+ @actions << action
123
+ self
124
+ end
125
+ end
126
+ end
127
+ end
@@ -37,10 +37,10 @@ module Elastomer
37
37
  yield msearch_obj = MultiSearch.new(self, params)
38
38
  msearch_obj.call
39
39
  else
40
- raise 'multi_search request body cannot be nil' if body.nil?
40
+ raise "multi_search request body cannot be nil" if body.nil?
41
41
  params ||= {}
42
42
 
43
- response = self.post '{/index}{/type}/_msearch', params.merge(:body => body)
43
+ response = self.post "{/index}{/type}/_msearch", params.merge(:body => body)
44
44
  response.body
45
45
  end
46
46
  end
@@ -49,7 +49,7 @@ module Elastomer
49
49
  #
50
50
  # Returns the response as a Hash
51
51
  def info( params = {} )
52
- response = client.get '/_nodes{/node_id}{/info}', update_params(params, :action => 'nodes.info')
52
+ response = client.get "/_nodes{/node_id}{/info}", update_params(params, :action => "nodes.info")
53
53
  response.body
54
54
  end
55
55
 
@@ -69,7 +69,7 @@ module Elastomer
69
69
  #
70
70
  # Returns the response as a Hash
71
71
  def stats( params = {} )
72
- response = client.get '/_nodes{/node_id}/stats{/stats}', update_params(params, :action => 'nodes.stats')
72
+ response = client.get "/_nodes{/node_id}/stats{/stats}", update_params(params, :action => "nodes.stats")
73
73
  response.body
74
74
  end
75
75
 
@@ -87,7 +87,7 @@ module Elastomer
87
87
  #
88
88
  # Returns the response as a String
89
89
  def hot_threads( params = {} )
90
- response = client.get '/_nodes{/node_id}/hot_threads', update_params(params, :action => 'nodes.hot_threads')
90
+ response = client.get "/_nodes{/node_id}/hot_threads", update_params(params, :action => "nodes.hot_threads")
91
91
  response.body
92
92
  end
93
93
 
@@ -101,7 +101,7 @@ module Elastomer
101
101
  #
102
102
  # Returns the response as a Hash
103
103
  def shutdown( params = {} )
104
- response = client.post '/_cluster/nodes{/node_id}/_shutdown', update_params(params, :action => 'nodes.shutdown')
104
+ response = client.post "/_cluster/nodes{/node_id}/_shutdown", update_params(params, :action => "nodes.shutdown")
105
105
  response.body
106
106
  end
107
107
 
@@ -0,0 +1,77 @@
1
+ module Elastomer
2
+ class Client
3
+
4
+ class Percolator
5
+
6
+ # Create a new Percolator for managing a query.
7
+ #
8
+ # client - Elastomer::Client used for HTTP requests to the server
9
+ # index_name - The index name
10
+ # id - The _id for the query
11
+ def initialize(client, index_name, id)
12
+ @client = client
13
+ @index_name = client.assert_param_presence(index_name, "index name")
14
+ @id = client.assert_param_presence(id, "id")
15
+ end
16
+
17
+ attr_reader :client, :index_name, :id
18
+
19
+ # Create a percolator query.
20
+ #
21
+ # Examples
22
+ #
23
+ # percolator = $client.index("default-index").percolator "1"
24
+ # percolator.create :query => { :match_all => { } }
25
+ #
26
+ # Returns the response body as a Hash
27
+ def create(body, params = {})
28
+ response = client.put("/{index}/.percolator/{id}", defaults.merge(params.merge(:body => body, :action => "percolator.create")))
29
+ response.body
30
+ end
31
+
32
+ # Gets a percolator query.
33
+ #
34
+ # Examples
35
+ #
36
+ # percolator = $client.index("default-index").percolator "1"
37
+ # percolator.get
38
+ #
39
+ # Returns the response body as a Hash
40
+ def get(params = {})
41
+ response = client.get("/{index}/.percolator/{id}", defaults.merge(params.merge(:action => "percolator.get")))
42
+ response.body
43
+ end
44
+
45
+ # Delete a percolator query.
46
+ #
47
+ # Examples
48
+ #
49
+ # percolator = $client.index("default-index").percolator "1"
50
+ # percolator.delete
51
+ #
52
+ # Returns the response body as a Hash
53
+ def delete(params = {})
54
+ response = client.delete("/{index}/.percolator/{id}", defaults.merge(params.merge(:action => "percolator.delete")))
55
+ response.body
56
+ end
57
+
58
+ # Checks for the existence of a percolator query.
59
+ #
60
+ # Examples
61
+ #
62
+ # percolator = $client.index("default-index").percolator "1"
63
+ # percolator.exists?
64
+ #
65
+ # Returns a boolean
66
+ def exists?(params = {})
67
+ get(params)["found"]
68
+ end
69
+
70
+ # Internal: Returns a Hash containing default parameters.
71
+ def defaults
72
+ {:index => index_name, :id => id}
73
+ end
74
+
75
+ end # Percolator
76
+ end # Client
77
+ end # Elastomer
@@ -14,7 +14,7 @@ module Elastomer
14
14
  # name - The name of the index as a String or an Array of names
15
15
  def initialize(client, name = nil)
16
16
  @client = client
17
- @name = @client.assert_param_presence(name, 'repository name') unless name.nil?
17
+ @name = @client.assert_param_presence(name, "repository name") unless name.nil?
18
18
  end
19
19
 
20
20
  attr_reader :client, :name
@@ -26,7 +26,7 @@ module Elastomer
26
26
  #
27
27
  # Returns true if the repository exists
28
28
  def exists?(params = {})
29
- response = client.get '/_snapshot{/repository}', update_params(params, :action => 'repository.exists')
29
+ response = client.get "/_snapshot{/repository}", update_params(params, :action => "repository.exists")
30
30
  response.success?
31
31
  rescue Elastomer::Client::Error => exception
32
32
  if exception.message =~ /RepositoryMissingException/
@@ -45,7 +45,7 @@ module Elastomer
45
45
  #
46
46
  # Returns the response body as a Hash
47
47
  def create(body, params = {})
48
- response = client.put '/_snapshot/{repository}', update_params(params, :body => body, :action => 'repository.create')
48
+ response = client.put "/_snapshot/{repository}", update_params(params, :body => body, :action => "repository.create")
49
49
  response.body
50
50
  end
51
51
 
@@ -56,7 +56,7 @@ module Elastomer
56
56
  #
57
57
  # Returns the response body as a Hash
58
58
  def get(params = {})
59
- response = client.get '/_snapshot{/repository}', update_params(params, :action => 'repository.get')
59
+ response = client.get "/_snapshot{/repository}", update_params(params, :action => "repository.get")
60
60
  response.body
61
61
  end
62
62
 
@@ -67,7 +67,7 @@ module Elastomer
67
67
  #
68
68
  # Returns the response body as a Hash
69
69
  def status(params = {})
70
- response = client.get '/_snapshot{/repository}/_status', update_params(params, :action => 'repository.status')
70
+ response = client.get "/_snapshot{/repository}/_status", update_params(params, :action => "repository.status")
71
71
  response.body
72
72
  end
73
73
 
@@ -79,7 +79,7 @@ module Elastomer
79
79
  #
80
80
  # Returns the response body as a Hash
81
81
  def update(body, params = {})
82
- response = client.put '/_snapshot/{repository}', update_params(params, :body => body, :action => 'repository.update')
82
+ response = client.put "/_snapshot/{repository}", update_params(params, :body => body, :action => "repository.update")
83
83
  response.body
84
84
  end
85
85
 
@@ -90,7 +90,7 @@ module Elastomer
90
90
  #
91
91
  # Returns the response body as a Hash
92
92
  def delete(params = {})
93
- response = client.delete '/_snapshot/{repository}', update_params(params, :action => 'repository.delete')
93
+ response = client.delete "/_snapshot/{repository}", update_params(params, :action => "repository.delete")
94
94
  response.body
95
95
  end
96
96
 
@@ -43,7 +43,7 @@ module Elastomer
43
43
  #
44
44
  # Returns a new Scroller instance
45
45
  def scan( query, opts = {} )
46
- opts = opts.merge(:search_type => 'scan')
46
+ opts = opts.merge(:search_type => "scan")
47
47
  Scroller.new(self, query, opts)
48
48
  end
49
49
 
@@ -72,8 +72,8 @@ module Elastomer
72
72
  #
73
73
  # Returns the response body as a Hash.
74
74
  def start_scroll( opts = {} )
75
- opts = opts.merge :action => 'search.start_scroll'
76
- response = get '{/index}{/type}/_search', opts
75
+ opts = opts.merge :action => "search.start_scroll"
76
+ response = get "{/index}{/type}/_search", opts
77
77
  response.body
78
78
  end
79
79
 
@@ -96,15 +96,15 @@ module Elastomer
96
96
  # # repeat until the results are empty
97
97
  #
98
98
  # Returns the response body as a Hash.
99
- def continue_scroll( scroll_id, scroll = '5m' )
100
- response = get '/_search/scroll', :body => scroll_id, :scroll => scroll, :action => 'search.scroll'
99
+ def continue_scroll( scroll_id, scroll = "5m" )
100
+ response = get "/_search/scroll", :body => scroll_id, :scroll => scroll, :action => "search.scroll"
101
101
  response.body
102
102
  end
103
103
 
104
104
  DEFAULT_OPTS = {
105
105
  :index => nil,
106
106
  :type => nil,
107
- :scroll => '5m',
107
+ :scroll => "5m",
108
108
  :size => 50,
109
109
  }.freeze
110
110
 
@@ -165,11 +165,11 @@ module Elastomer
165
165
  loop do
166
166
  body = do_scroll
167
167
 
168
- hits = body['hits']
169
- break if hits['hits'].empty?
168
+ hits = body["hits"]
169
+ break if hits["hits"].empty?
170
170
 
171
- hits['offset'] = @offset
172
- @offset += hits['hits'].length
171
+ hits["offset"] = @offset
172
+ @offset += hits["hits"].length
173
173
 
174
174
  yield hits
175
175
  end
@@ -195,7 +195,7 @@ module Elastomer
195
195
  #
196
196
  # Returns this Scan instance.
197
197
  def each_document( &block )
198
- each { |hits| hits['hits'].each(&block) }
198
+ each { |hits| hits["hits"].each(&block) }
199
199
  end
200
200
 
201
201
  # Internal: Perform the actual scroll requests. This method wil call out
@@ -206,15 +206,15 @@ module Elastomer
206
206
  def do_scroll
207
207
  if scroll_id.nil?
208
208
  body = client.start_scroll(@opts)
209
- if body['hits']['hits'].empty?
210
- @scroll_id = body['_scroll_id']
209
+ if body["hits"]["hits"].empty?
210
+ @scroll_id = body["_scroll_id"]
211
211
  return do_scroll
212
212
  end
213
213
  else
214
214
  body = client.continue_scroll(scroll_id, @opts[:scroll])
215
215
  end
216
216
 
217
- @scroll_id = body['_scroll_id']
217
+ @scroll_id = body["_scroll_id"]
218
218
  body
219
219
  end
220
220
 
@@ -22,8 +22,8 @@ module Elastomer
22
22
  def initialize(client, repository = nil, name = nil)
23
23
  @client = client
24
24
  # don't allow nil repository if snapshot name is not nil
25
- @repository = @client.assert_param_presence(repository, 'repository name') unless repository.nil? && name.nil?
26
- @name = @client.assert_param_presence(name, 'snapshot name') unless name.nil?
25
+ @repository = @client.assert_param_presence(repository, "repository name") unless repository.nil? && name.nil?
26
+ @name = @client.assert_param_presence(name, "snapshot name") unless name.nil?
27
27
  end
28
28
 
29
29
  attr_reader :client, :repository, :name
@@ -35,7 +35,7 @@ module Elastomer
35
35
  #
36
36
  # Returns true if the snapshot exists
37
37
  def exists?(params = {})
38
- response = client.get '/_snapshot/{repository}/{snapshot}', update_params(params, :action => 'snapshot.exists')
38
+ response = client.get "/_snapshot/{repository}/{snapshot}", update_params(params, :action => "snapshot.exists")
39
39
  response.success?
40
40
  rescue Elastomer::Client::Error => exception
41
41
  if exception.message =~ /SnapshotMissingException/
@@ -54,7 +54,7 @@ module Elastomer
54
54
  #
55
55
  # Returns the response body as a Hash
56
56
  def create(body = {}, params = {})
57
- response = client.put '/_snapshot/{repository}/{snapshot}', update_params(params, :body => body, :action => 'snapshot.create')
57
+ response = client.put "/_snapshot/{repository}/{snapshot}", update_params(params, :body => body, :action => "snapshot.create")
58
58
  response.body
59
59
  end
60
60
 
@@ -66,8 +66,8 @@ module Elastomer
66
66
  # Returns the response body as a Hash
67
67
  def get(params = {})
68
68
  # Set snapshot name or we'll get the repository instead
69
- snapshot = name || '_all'
70
- response = client.get '/_snapshot/{repository}/{snapshot}', update_params(params, :snapshot => snapshot, :action => 'snapshot.get')
69
+ snapshot = name || "_all"
70
+ response = client.get "/_snapshot/{repository}/{snapshot}", update_params(params, :snapshot => snapshot, :action => "snapshot.get")
71
71
  response.body
72
72
  end
73
73
 
@@ -78,7 +78,7 @@ module Elastomer
78
78
  #
79
79
  # Returns the response body as a Hash
80
80
  def status(params = {})
81
- response = client.get '/_snapshot{/repository}{/snapshot}/_status', update_params(params, :action => 'snapshot.status')
81
+ response = client.get "/_snapshot{/repository}{/snapshot}/_status", update_params(params, :action => "snapshot.status")
82
82
  response.body
83
83
  end
84
84
 
@@ -90,7 +90,7 @@ module Elastomer
90
90
  #
91
91
  # Returns the response body as a Hash
92
92
  def restore(body = {}, params = {})
93
- response = client.post '/_snapshot/{repository}/{snapshot}/_restore', update_params(params, :body => body, :action => 'snapshot.restore')
93
+ response = client.post "/_snapshot/{repository}/{snapshot}/_restore", update_params(params, :body => body, :action => "snapshot.restore")
94
94
  response.body
95
95
  end
96
96
 
@@ -101,7 +101,7 @@ module Elastomer
101
101
  #
102
102
  # Returns the response body as a Hash
103
103
  def delete(params = {})
104
- response = client.delete '/_snapshot/{repository}/{snapshot}', update_params(params, :action => 'snapshot.delete')
104
+ response = client.delete "/_snapshot/{repository}/{snapshot}", update_params(params, :action => "snapshot.delete")
105
105
  response.body
106
106
  end
107
107