rubberband 0.0.5 → 0.0.6
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.
- data/README.rdoc +5 -5
- data/Rakefile +1 -1
- data/TODO +8 -28
- data/lib/elasticsearch/client/index.rb +26 -6
- data/lib/elasticsearch/transport.rb +1 -0
- data/lib/elasticsearch/transport/base_protocol.rb +9 -1
- data/lib/elasticsearch/transport/http.rb +1 -1
- data/lib/elasticsearch/transport/memcached.rb +72 -0
- data/lib/elasticsearch/transport/thrift.rb +1 -1
- data/lib/elasticsearch/version.rb +1 -1
- data/rubberband.gemspec +6 -3
- data/test/type_test.rb +44 -0
- metadata +7 -4
data/README.rdoc
CHANGED
@@ -9,8 +9,9 @@ Copyright 2010 Grant Rodgers. See included LICENSE file.
|
|
9
9
|
|
10
10
|
== Features
|
11
11
|
|
12
|
-
* Automatic failover and
|
13
|
-
* Multiple transports
|
12
|
+
* Automatic failover, retry, and peer discovery
|
13
|
+
* Multiple transports (HTTP, Thrift, Memcached TODO)
|
14
|
+
* Multiple encodings (JSON (Yajl), Smile TODO)
|
14
15
|
|
15
16
|
== Usage
|
16
17
|
|
@@ -18,7 +19,7 @@ Instantiate a client:
|
|
18
19
|
|
19
20
|
client = ElasticSearch.new('127.0.0.1:9200', :index => "twitter", :type => "tweet")
|
20
21
|
|
21
|
-
API
|
22
|
+
API:
|
22
23
|
|
23
24
|
client.index({:body => "elasticsearch is cool"}, :id => 1)
|
24
25
|
client.get("1")
|
@@ -26,8 +27,7 @@ API is subject to change, but here is a trivial example:
|
|
26
27
|
|
27
28
|
== TODO
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
See TODO file.
|
31
31
|
|
32
32
|
== Contributing
|
33
33
|
|
data/Rakefile
CHANGED
data/TODO
CHANGED
@@ -1,29 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
search*
|
8
|
-
terms
|
9
|
-
more_like_this
|
10
|
-
admin index api:
|
11
|
-
status*
|
12
|
-
create*
|
13
|
-
delete*
|
14
|
-
alias*
|
15
|
-
mapping*
|
16
|
-
flush*
|
17
|
-
refresh*
|
18
|
-
snapshot*
|
19
|
-
optimize*
|
20
|
-
admin cluster api:
|
21
|
-
health*
|
22
|
-
state*
|
23
|
-
nodes info*
|
24
|
-
nodes stats*
|
25
|
-
nodes shutdown*
|
26
|
-
nodes restart*
|
27
|
-
|
28
|
-
handle partial failure cases where some shards are unsuccessful (maybe raise a PartialResult exception, allow override option to return results anyway. results should have a flag that signifies incompleteness)
|
1
|
+
delete_by_query
|
2
|
+
terms
|
3
|
+
more_like_this
|
4
|
+
bulk ops
|
5
|
+
test scroll better, maybe add a scroller object
|
6
|
+
handle partial failure cases where some shards are unsuccessful (optionally raise a PartialResult exception, allow override option to return results anyway. results should have a flag that signifies incompleteness)
|
29
7
|
tests/specs/features
|
8
|
+
memcached transport
|
9
|
+
smile encoding
|
@@ -13,11 +13,16 @@ module ElasticSearch
|
|
13
13
|
# timeout (optional)
|
14
14
|
# document (optional)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if @batch
|
17
|
+
@batch << { :index => { :_index => options[:index], :_type => options[:type], :_id => options[:id] }}
|
18
|
+
@batch << document
|
19
19
|
else
|
20
|
-
|
20
|
+
result = execute(:index, options[:index], options[:type], options[:id], document, options)
|
21
|
+
if result["ok"]
|
22
|
+
result["_id"]
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
@@ -38,8 +43,13 @@ module ElasticSearch
|
|
38
43
|
def delete(id, options={})
|
39
44
|
set_default_scope!(options)
|
40
45
|
raise "index and type or defaults required" unless options[:index] && options[:type]
|
41
|
-
|
42
|
-
|
46
|
+
|
47
|
+
if @batch
|
48
|
+
@batch << { :delete => { :_index => options[:index], :_type => options[:type], :_id => id }}
|
49
|
+
else
|
50
|
+
result = execute(:delete, options[:index], options[:type], id, options)
|
51
|
+
result["ok"]
|
52
|
+
end
|
43
53
|
end
|
44
54
|
|
45
55
|
#df The default field to use when no field prefix is defined within the query.
|
@@ -89,6 +99,16 @@ module ElasticSearch
|
|
89
99
|
response["count"].to_i #TODO check if count is nil
|
90
100
|
end
|
91
101
|
|
102
|
+
# Starts a bulk operation batch and yields self. Index and delete requests will be
|
103
|
+
# queued until the block closes, then sent as a single _bulk call.
|
104
|
+
def bulk
|
105
|
+
@batch = []
|
106
|
+
yield(self)
|
107
|
+
response = execute(:bulk, @batch)
|
108
|
+
ensure
|
109
|
+
@batch = nil
|
110
|
+
end
|
111
|
+
|
92
112
|
private
|
93
113
|
|
94
114
|
def slice_hash(hash, *keys)
|
@@ -68,6 +68,13 @@ module ElasticSearch
|
|
68
68
|
handle_error(response) unless response.status == 200
|
69
69
|
encoder.decode(response.body) # {"count", "_shards"=>{"failed", "total", "successful"}}
|
70
70
|
end
|
71
|
+
|
72
|
+
def bulk(actions)
|
73
|
+
body = actions.inject("") { |a, s| a << encoder.encode(s) << "\n" }
|
74
|
+
response = request(:post, {:op => '_bulk'}, {}, body)
|
75
|
+
handle_error(response) unless response.status == 200
|
76
|
+
encoder.decode(response.body) # {"items => [ {"delete"/"create" => {"_index", "_type", "_id", "ok"}} ] }
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
80
|
module IndexAdminProtocol
|
@@ -154,8 +161,9 @@ module ElasticSearch
|
|
154
161
|
def generate_uri(options)
|
155
162
|
path = ""
|
156
163
|
path << "/#{Array(options[:index]).collect { |i| escape(i.downcase) }.join(",")}" if options[:index] && !options[:index].empty?
|
164
|
+
path << "/" if options[:index] && options[:index].empty?
|
157
165
|
path << "/#{Array(options[:type]).collect { |t| escape(t) }.join(",")}" if options[:type] && !options[:type].empty?
|
158
|
-
path << "/#{Array(options[:id]).collect { |id| escape(id) }.join(",")}" if options[:id] && !options[:id].empty?
|
166
|
+
path << "/#{Array(options[:id]).collect { |id| escape(id) }.join(",")}" if options[:id] && !options[:id].to_s.empty?
|
159
167
|
path << "/#{options[:op]}" if options[:op]
|
160
168
|
path
|
161
169
|
end
|
@@ -38,7 +38,7 @@ module ElasticSearch
|
|
38
38
|
uri = generate_uri(operation)
|
39
39
|
query = generate_query_string(params)
|
40
40
|
path = [uri, query].join("?")
|
41
|
-
#puts "request: #{@server} #{path} #{body}"
|
41
|
+
#puts "request: #{method} #{@server} #{path} #{body}"
|
42
42
|
response = @session.request(method, path, headers, :data => body)
|
43
43
|
handle_error(response) if response.status >= 500
|
44
44
|
response
|
@@ -0,0 +1,72 @@
|
|
1
|
+
begin
|
2
|
+
require 'memcached'
|
3
|
+
rescue LoadError => error
|
4
|
+
raise "Please install the memcached gem to use the memcached transport."
|
5
|
+
end
|
6
|
+
|
7
|
+
module ElasticSearch
|
8
|
+
module Transport
|
9
|
+
class Memcached < Base
|
10
|
+
Response = Struct.new(:status, :headers, :body)
|
11
|
+
|
12
|
+
DEFAULTS = {
|
13
|
+
:timeout => 5
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
def initialize(server, options={})
|
17
|
+
super
|
18
|
+
@options = DEFAULTS.merge(@options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def connect!
|
22
|
+
@memcached = ::Memcached.new(@server, :timeout => @options[:timeout]) #TODO allow passing other options?
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@memcached.quit
|
27
|
+
end
|
28
|
+
|
29
|
+
def all_nodes
|
30
|
+
memcached_addresses = nodes_info([])["nodes"].collect { |id, node| node["memcached_address"] }
|
31
|
+
memcached_addresses.collect! do |a|
|
32
|
+
if a =~ /inet\[.*\/([\d.:]+)\]/
|
33
|
+
$1
|
34
|
+
end
|
35
|
+
end.compact!
|
36
|
+
memcached_addresses
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def request(method, operation, params={}, body=nil, headers={})
|
42
|
+
begin
|
43
|
+
uri = generate_uri(operation)
|
44
|
+
query = generate_query_string(params)
|
45
|
+
path = [uri, query].join("?")
|
46
|
+
#puts "request: #{method} #{@server} #{path} #{body}"
|
47
|
+
response = case method
|
48
|
+
when :get
|
49
|
+
@memcached.get(path, false)
|
50
|
+
when :put, :post
|
51
|
+
#TODO put vs post?
|
52
|
+
@memcached.set(path, body, 0, false)
|
53
|
+
when :delete
|
54
|
+
@memcached.delete(path)
|
55
|
+
end
|
56
|
+
#puts "response: #{response}"
|
57
|
+
response = Response.new(200, {}, response) #TODO
|
58
|
+
handle_error(response) if response.status >= 500
|
59
|
+
response
|
60
|
+
rescue Exception => e
|
61
|
+
case e
|
62
|
+
when TimeoutError
|
63
|
+
raise TimeoutError
|
64
|
+
else
|
65
|
+
raise e
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -76,7 +76,7 @@ module ElasticSearch
|
|
76
76
|
when :get
|
77
77
|
request.method = ElasticSearch::Thrift::Method::GET
|
78
78
|
when :put
|
79
|
-
request.method = ElasticSearch::Thrift::Method::
|
79
|
+
request.method = ElasticSearch::Thrift::Method::PUT
|
80
80
|
when :post
|
81
81
|
request.method = ElasticSearch::Thrift::Method::POST
|
82
82
|
when :delete
|
data/rubberband.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rubberband}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["grantr"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-01-07}
|
13
13
|
s.description = %q{An ElasticSearch client with ThriftClient-like failover handling.}
|
14
14
|
s.email = %q{grantr@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -41,6 +41,7 @@ Gem::Specification.new do |s|
|
|
41
41
|
"lib/elasticsearch/transport/base.rb",
|
42
42
|
"lib/elasticsearch/transport/base_protocol.rb",
|
43
43
|
"lib/elasticsearch/transport/http.rb",
|
44
|
+
"lib/elasticsearch/transport/memcached.rb",
|
44
45
|
"lib/elasticsearch/transport/thrift.rb",
|
45
46
|
"lib/elasticsearch/transport/thrift/elasticsearch_constants.rb",
|
46
47
|
"lib/elasticsearch/transport/thrift/elasticsearch_types.rb",
|
@@ -51,6 +52,7 @@ Gem::Specification.new do |s|
|
|
51
52
|
"test/elasticsearch_test.rb",
|
52
53
|
"test/hits_test.rb",
|
53
54
|
"test/test_helper.rb",
|
55
|
+
"test/type_test.rb",
|
54
56
|
"vendor/elasticsearch/elasticsearch.thrift"
|
55
57
|
]
|
56
58
|
s.homepage = %q{http://github.com/grantr/rubberband}
|
@@ -61,7 +63,8 @@ Gem::Specification.new do |s|
|
|
61
63
|
s.test_files = [
|
62
64
|
"test/elasticsearch_test.rb",
|
63
65
|
"test/hits_test.rb",
|
64
|
-
"test/test_helper.rb"
|
66
|
+
"test/test_helper.rb",
|
67
|
+
"test/type_test.rb"
|
65
68
|
]
|
66
69
|
|
67
70
|
if s.respond_to? :specification_version then
|
data/test/type_test.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TypeTest < Test::Unit::TestCase
|
4
|
+
context "Test with differents Types" do
|
5
|
+
#TODO figure out how to have one setup and one teardown
|
6
|
+
setup do
|
7
|
+
@client = ElasticSearch.new('127.0.0.1:9200', :index => "twitter", :type => "tweet")
|
8
|
+
@client.index({:user => "kimchy"}, :id => 1)
|
9
|
+
@client.index({:user => "kimchy"}, :id => 2, :type => "grillo")
|
10
|
+
@client.index({:user => "kimchy"}, :id => 3, :type => "cote")
|
11
|
+
@client.index({:user => "kimchy"}, :id => 4, :index => "cotes", :type => "cote")
|
12
|
+
@client.index({:user => "kimchy"}, :id => 5, :index => "menchos", :type => "mencho")
|
13
|
+
@client.index({:user => "kimchy"}, :id => 6, :index => "menchos", :type => "cote")
|
14
|
+
@client.refresh("twitter", "cotes", "menchos")
|
15
|
+
end
|
16
|
+
|
17
|
+
teardown do
|
18
|
+
#@client.delete_index("twitter")
|
19
|
+
#@client.delete_index("cotes")
|
20
|
+
#@client.delete_index("menchos")
|
21
|
+
end
|
22
|
+
|
23
|
+
should "search in all indexes" do
|
24
|
+
assert_equal @client.count("kimchy",{:index => "", :type => ""}), 6
|
25
|
+
end
|
26
|
+
|
27
|
+
should "search in all types with index twitter" do
|
28
|
+
assert_equal @client.count("kimchy",{:index => "twitter", :type => ""}), 3
|
29
|
+
end
|
30
|
+
|
31
|
+
should "search in index twitter with types tweet,cote" do
|
32
|
+
assert_equal @client.count("kimchy",{:index => "twitter", :type => "tweet,cote"}), 2
|
33
|
+
end
|
34
|
+
|
35
|
+
should "search in index twitter,cotes" do
|
36
|
+
assert_equal @client.count("kimchy",{:index => "twitter,cotes", :type => ""}), 4
|
37
|
+
end
|
38
|
+
|
39
|
+
should "search in types grillo,cote of all indexes" do
|
40
|
+
assert_equal @client.count("kimchy",{:index => "", :type => "grillo,cote"}), 4
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 6
|
9
|
+
version: 0.0.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- grantr
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-07 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- lib/elasticsearch/transport/base.rb
|
134
134
|
- lib/elasticsearch/transport/base_protocol.rb
|
135
135
|
- lib/elasticsearch/transport/http.rb
|
136
|
+
- lib/elasticsearch/transport/memcached.rb
|
136
137
|
- lib/elasticsearch/transport/thrift.rb
|
137
138
|
- lib/elasticsearch/transport/thrift/elasticsearch_constants.rb
|
138
139
|
- lib/elasticsearch/transport/thrift/elasticsearch_types.rb
|
@@ -143,6 +144,7 @@ files:
|
|
143
144
|
- test/elasticsearch_test.rb
|
144
145
|
- test/hits_test.rb
|
145
146
|
- test/test_helper.rb
|
147
|
+
- test/type_test.rb
|
146
148
|
- vendor/elasticsearch/elasticsearch.thrift
|
147
149
|
has_rdoc: true
|
148
150
|
homepage: http://github.com/grantr/rubberband
|
@@ -158,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
158
160
|
requirements:
|
159
161
|
- - ">="
|
160
162
|
- !ruby/object:Gem::Version
|
161
|
-
hash: -
|
163
|
+
hash: -3014120754088484755
|
162
164
|
segments:
|
163
165
|
- 0
|
164
166
|
version: "0"
|
@@ -181,3 +183,4 @@ test_files:
|
|
181
183
|
- test/elasticsearch_test.rb
|
182
184
|
- test/hits_test.rb
|
183
185
|
- test/test_helper.rb
|
186
|
+
- test/type_test.rb
|