riak-client 0.8.3 → 0.9.0.beta
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/Rakefile +10 -3
- data/lib/riak/bucket.rb +31 -46
- data/lib/riak/client.rb +18 -4
- data/lib/riak/client/excon_backend.rb +15 -1
- data/lib/riak/client/http_backend.rb +169 -196
- data/lib/riak/client/http_backend/configuration.rb +56 -0
- data/lib/riak/client/http_backend/object_methods.rb +101 -0
- data/lib/riak/client/http_backend/request_headers.rb +46 -0
- data/lib/riak/client/http_backend/transport_methods.rb +208 -0
- data/lib/riak/core_ext/blank.rb +14 -2
- data/lib/riak/link.rb +9 -4
- data/lib/riak/locale/en.yml +2 -0
- data/lib/riak/map_reduce.rb +37 -103
- data/lib/riak/map_reduce/filter_builder.rb +106 -0
- data/lib/riak/map_reduce/phase.rb +108 -0
- data/lib/riak/robject.rb +19 -96
- data/lib/riak/util/escape.rb +7 -0
- data/riak-client.gemspec +5 -5
- data/spec/riak/bucket_spec.rb +57 -111
- data/spec/riak/client_spec.rb +97 -78
- data/spec/riak/escape_spec.rb +7 -0
- data/spec/riak/http_backend/object_methods_spec.rb +218 -0
- data/spec/riak/http_backend_spec.rb +204 -65
- data/spec/riak/link_spec.rb +8 -0
- data/spec/riak/map_reduce_spec.rb +26 -151
- data/spec/riak/object_spec.rb +36 -350
- data/spec/riak/search_spec.rb +5 -16
- data/spec/spec_helper.rb +1 -1
- metadata +29 -8
data/lib/riak/util/escape.rb
CHANGED
@@ -23,6 +23,13 @@ module Riak
|
|
23
23
|
def escape(bucket_or_key)
|
24
24
|
CGI.escape(bucket_or_key.to_s).gsub("+", "%20")
|
25
25
|
end
|
26
|
+
|
27
|
+
# CGI-unescapes bucket or key names
|
28
|
+
# @param [String] bucket_or_key the bucket or key name
|
29
|
+
# @return [String] the unescaped name
|
30
|
+
def unescape(bucket_or_key)
|
31
|
+
CGI.unescape(bucket_or_key.to_s)
|
32
|
+
end
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
data/riak-client.gemspec
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{riak-client}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.9.0.beta"
|
6
6
|
|
7
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Sean Cribbs"]
|
9
|
-
s.date = %q{2010-12-
|
9
|
+
s.date = %q{2010-12-29}
|
10
10
|
s.description = %q{riak-client is a rich client for Riak, the distributed database by Basho. It supports the full HTTP interface including storage operations, bucket configuration, link-walking and map-reduce.}
|
11
11
|
s.email = %q{sean@basho.com}
|
12
|
-
s.files = ["erl_src/riak_kv_test_backend.beam", "erl_src/riak_kv_test_backend.erl", "Gemfile", "lib/active_support/cache/riak_store.rb", "lib/riak/bucket.rb", "lib/riak/cache_store.rb", "lib/riak/client/curb_backend.rb", "lib/riak/client/excon_backend.rb", "lib/riak/client/http_backend.rb", "lib/riak/client/net_http_backend.rb", "lib/riak/client.rb", "lib/riak/core_ext/blank.rb", "lib/riak/core_ext/extract_options.rb", "lib/riak/core_ext/slice.rb", "lib/riak/core_ext/stringify_keys.rb", "lib/riak/core_ext/symbolize_keys.rb", "lib/riak/core_ext/to_param.rb", "lib/riak/core_ext.rb", "lib/riak/failed_request.rb", "lib/riak/i18n.rb", "lib/riak/invalid_response.rb", "lib/riak/link.rb", "lib/riak/locale/en.yml", "lib/riak/map_reduce.rb", "lib/riak/map_reduce_error.rb", "lib/riak/robject.rb", "lib/riak/search.rb", "lib/riak/test_server.rb", "lib/riak/util/escape.rb", "lib/riak/util/fiber1.8.rb", "lib/riak/util/headers.rb", "lib/riak/util/multipart.rb", "lib/riak/util/tcp_socket_extensions.rb", "lib/riak/util/translation.rb", "lib/riak/walk_spec.rb", "lib/riak.rb", "Rakefile", "riak-client.gemspec", "spec/fixtures/cat.jpg", "spec/fixtures/multipart-blank.txt", "spec/fixtures/multipart-with-body.txt", "spec/integration/riak/cache_store_spec.rb", "spec/integration/riak/test_server_spec.rb", "spec/riak/bucket_spec.rb", "spec/riak/client_spec.rb", "spec/riak/curb_backend_spec.rb", "spec/riak/escape_spec.rb", "spec/riak/excon_backend_spec.rb", "spec/riak/headers_spec.rb", "spec/riak/http_backend_spec.rb", "spec/riak/link_spec.rb", "spec/riak/map_reduce_spec.rb", "spec/riak/multipart_spec.rb", "spec/riak/net_http_backend_spec.rb", "spec/riak/object_spec.rb", "spec/riak/search_spec.rb", "spec/riak/walk_spec_spec.rb", "spec/spec_helper.rb", "spec/support/drb_mock_server.rb", "spec/support/http_backend_implementation_examples.rb", "spec/support/mock_server.rb", "spec/support/mocks.rb", "spec/support/test_server.yml.example"]
|
12
|
+
s.files = ["erl_src/riak_kv_test_backend.beam", "erl_src/riak_kv_test_backend.erl", "Gemfile", "lib/active_support/cache/riak_store.rb", "lib/riak/bucket.rb", "lib/riak/cache_store.rb", "lib/riak/client/curb_backend.rb", "lib/riak/client/excon_backend.rb", "lib/riak/client/http_backend/configuration.rb", "lib/riak/client/http_backend/object_methods.rb", "lib/riak/client/http_backend/request_headers.rb", "lib/riak/client/http_backend/transport_methods.rb", "lib/riak/client/http_backend.rb", "lib/riak/client/net_http_backend.rb", "lib/riak/client.rb", "lib/riak/core_ext/blank.rb", "lib/riak/core_ext/extract_options.rb", "lib/riak/core_ext/slice.rb", "lib/riak/core_ext/stringify_keys.rb", "lib/riak/core_ext/symbolize_keys.rb", "lib/riak/core_ext/to_param.rb", "lib/riak/core_ext.rb", "lib/riak/failed_request.rb", "lib/riak/i18n.rb", "lib/riak/invalid_response.rb", "lib/riak/link.rb", "lib/riak/locale/en.yml", "lib/riak/map_reduce/filter_builder.rb", "lib/riak/map_reduce/phase.rb", "lib/riak/map_reduce.rb", "lib/riak/map_reduce_error.rb", "lib/riak/robject.rb", "lib/riak/search.rb", "lib/riak/test_server.rb", "lib/riak/util/escape.rb", "lib/riak/util/fiber1.8.rb", "lib/riak/util/headers.rb", "lib/riak/util/multipart.rb", "lib/riak/util/tcp_socket_extensions.rb", "lib/riak/util/translation.rb", "lib/riak/walk_spec.rb", "lib/riak.rb", "Rakefile", "riak-client.gemspec", "spec/fixtures/cat.jpg", "spec/fixtures/multipart-blank.txt", "spec/fixtures/multipart-with-body.txt", "spec/integration/riak/cache_store_spec.rb", "spec/integration/riak/test_server_spec.rb", "spec/riak/bucket_spec.rb", "spec/riak/client_spec.rb", "spec/riak/curb_backend_spec.rb", "spec/riak/escape_spec.rb", "spec/riak/excon_backend_spec.rb", "spec/riak/headers_spec.rb", "spec/riak/http_backend/object_methods_spec.rb", "spec/riak/http_backend_spec.rb", "spec/riak/link_spec.rb", "spec/riak/map_reduce_spec.rb", "spec/riak/multipart_spec.rb", "spec/riak/net_http_backend_spec.rb", "spec/riak/object_spec.rb", "spec/riak/search_spec.rb", "spec/riak/walk_spec_spec.rb", "spec/spec_helper.rb", "spec/support/drb_mock_server.rb", "spec/support/http_backend_implementation_examples.rb", "spec/support/mock_server.rb", "spec/support/mocks.rb", "spec/support/test_server.yml.example"]
|
13
13
|
s.homepage = %q{http://seancribbs.github.com/ripple}
|
14
14
|
s.require_paths = ["lib"]
|
15
15
|
s.rubygems_version = %q{1.3.7}
|
16
16
|
s.summary = %q{riak-client is a rich client for Riak, the distributed database by Basho.}
|
17
|
-
s.test_files = ["lib/riak/walk_spec.rb", "spec/integration/riak/cache_store_spec.rb", "spec/integration/riak/test_server_spec.rb", "spec/riak/bucket_spec.rb", "spec/riak/client_spec.rb", "spec/riak/curb_backend_spec.rb", "spec/riak/escape_spec.rb", "spec/riak/excon_backend_spec.rb", "spec/riak/headers_spec.rb", "spec/riak/http_backend_spec.rb", "spec/riak/link_spec.rb", "spec/riak/map_reduce_spec.rb", "spec/riak/multipart_spec.rb", "spec/riak/net_http_backend_spec.rb", "spec/riak/object_spec.rb", "spec/riak/search_spec.rb", "spec/riak/walk_spec_spec.rb"]
|
17
|
+
s.test_files = ["lib/riak/walk_spec.rb", "spec/integration/riak/cache_store_spec.rb", "spec/integration/riak/test_server_spec.rb", "spec/riak/bucket_spec.rb", "spec/riak/client_spec.rb", "spec/riak/curb_backend_spec.rb", "spec/riak/escape_spec.rb", "spec/riak/excon_backend_spec.rb", "spec/riak/headers_spec.rb", "spec/riak/http_backend/object_methods_spec.rb", "spec/riak/http_backend_spec.rb", "spec/riak/link_spec.rb", "spec/riak/map_reduce_spec.rb", "spec/riak/multipart_spec.rb", "spec/riak/net_http_backend_spec.rb", "spec/riak/object_spec.rb", "spec/riak/search_spec.rb", "spec/riak/walk_spec_spec.rb"]
|
18
18
|
|
19
19
|
if s.respond_to? :specification_version then
|
20
20
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
data/spec/riak/bucket_spec.rb
CHANGED
@@ -16,24 +16,11 @@ require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
|
16
16
|
describe Riak::Bucket do
|
17
17
|
before :each do
|
18
18
|
@client = Riak::Client.new
|
19
|
+
@backend = mock("Backend")
|
20
|
+
@client.stub!(:backend).and_return(@backend)
|
19
21
|
@bucket = Riak::Bucket.new(@client, "foo")
|
20
22
|
end
|
21
23
|
|
22
|
-
def do_load(overrides={})
|
23
|
-
@bucket.load({
|
24
|
-
:body => '{"props":{"name":"foo","n_val":3,"allow_mult":false,"last_write_wins":false,"precommit":[],"postcommit":[],"chash_keyfun":{"mod":"riak_core_util","fun":"chash_std_keyfun"},"linkfun":{"mod":"riak_kv_wm_link_walker","fun":"mapreduce_linkfun"},"old_vclock":86400,"young_vclock":20,"big_vclock":50,"small_vclock":10,"r":"quorum","w":"quorum","dw":"quorum","rw":"quorum"},"keys":["bar"]}',
|
25
|
-
:headers => {
|
26
|
-
"vary" => ["Accept-Encoding"],
|
27
|
-
"server" => ["MochiWeb/1.1 WebMachine/1.5.1 (hack the charles gibson)"],
|
28
|
-
"link" => ['</riak/foo/bar>; riaktag="contained"'],
|
29
|
-
"date" => ["Tue, 12 Jan 2010 15:30:43 GMT"],
|
30
|
-
"content-type" => ["application/json"],
|
31
|
-
"content-length" => ["257"]
|
32
|
-
}
|
33
|
-
}.merge(overrides))
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
24
|
describe "when initializing" do
|
38
25
|
it "should require a client and a name" do
|
39
26
|
lambda { Riak::Bucket.new }.should raise_error
|
@@ -50,116 +37,69 @@ describe Riak::Bucket do
|
|
50
37
|
end
|
51
38
|
end
|
52
39
|
|
53
|
-
describe "when loading data from an HTTP response" do
|
54
|
-
it "should load the bucket properties from the response body" do
|
55
|
-
do_load
|
56
|
-
@bucket.props.should == {"name"=>"foo", "n_val"=>3, "allow_mult"=>false, "last_write_wins"=>false, "precommit"=>[], "postcommit"=>[], "chash_keyfun"=>{"mod"=>"riak_core_util", "fun"=>"chash_std_keyfun"}, "linkfun"=>{"mod"=>"riak_kv_wm_link_walker", "fun"=>"mapreduce_linkfun"}, "old_vclock"=>86400, "young_vclock"=>20, "big_vclock"=>50, "small_vclock"=>10, "r"=>"quorum", "w"=>"quorum", "dw"=>"quorum", "rw"=>"quorum"}
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should load the keys from the response body" do
|
60
|
-
do_load
|
61
|
-
@bucket.keys.should == ["bar"]
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should raise an error for a response that is not JSON" do
|
65
|
-
lambda do
|
66
|
-
do_load(:headers => {"content-type" => ["text/plain"]})
|
67
|
-
end.should raise_error(Riak::InvalidResponse)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should unescape key names" do
|
71
|
-
do_load(:body => '{"keys":["foo", "bar%20baz"]}')
|
72
|
-
@bucket.keys.should == ["foo", "bar baz"]
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
40
|
describe "accessing keys" do
|
77
|
-
before :each do
|
78
|
-
@http = mock("HTTPBackend")
|
79
|
-
@client.stub!(:http).and_return(@http)
|
80
|
-
end
|
81
|
-
|
82
41
|
it "should load the keys if not present" do
|
83
|
-
@
|
42
|
+
@backend.should_receive(:list_keys).with(@bucket).and_return(["bar"])
|
84
43
|
@bucket.keys.should == ["bar"]
|
85
44
|
end
|
86
45
|
|
87
46
|
it "should allow reloading of the keys" do
|
88
|
-
@
|
89
|
-
|
47
|
+
@backend.should_receive(:list_keys).with(@bucket).and_return(["bar"])
|
48
|
+
@bucket.instance_variable_set(:@keys, ["foo"])
|
90
49
|
@bucket.keys(:reload => true).should == ["bar"]
|
91
50
|
end
|
92
51
|
|
93
52
|
it "should allow streaming keys through block" do
|
94
|
-
|
95
|
-
@http.should_receive(:get).with(200, "/riak/","foo", {:props => false, :keys => "stream"}, {}).and_yield("{}").and_yield('{"keys":[]}').and_yield('{"keys":["bar"]}').and_yield('{"keys":["baz"]}')
|
53
|
+
@backend.should_receive(:list_keys).with(@bucket).and_yield([]).and_yield(["bar"]).and_yield(["baz"])
|
96
54
|
all_keys = []
|
97
55
|
@bucket.keys do |list|
|
98
56
|
all_keys.concat(list)
|
99
57
|
end
|
100
58
|
all_keys.should == ["bar", "baz"]
|
101
59
|
end
|
102
|
-
|
103
|
-
it "should unescape key names" do
|
104
|
-
@http.should_receive(:get).with(200, "/riak/","foo", {:props => false, :keys => true}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar%20baz"]}'})
|
105
|
-
@bucket.keys.should == ["bar baz"]
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should escape the bucket name" do
|
109
|
-
@bucket.instance_variable_set :@name, "unescaped "
|
110
|
-
@http.should_receive(:get).with(200, "/riak/","unescaped%20", {:props => false, :keys => true}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
|
111
|
-
@bucket.keys.should == ["bar"]
|
112
|
-
end
|
113
60
|
end
|
114
61
|
|
115
62
|
describe "setting the bucket properties" do
|
116
|
-
|
117
|
-
@
|
118
|
-
@
|
63
|
+
it "should prefetch the properties when they are not present" do
|
64
|
+
@backend.stub!(:set_bucket_props)
|
65
|
+
@backend.should_receive(:get_bucket_props).with(@bucket).and_return({"name" => "foo"})
|
66
|
+
@bucket.props = {"precommit" => []}
|
119
67
|
end
|
120
68
|
|
121
|
-
it "should
|
122
|
-
@
|
69
|
+
it "should set the new properties on the bucket" do
|
70
|
+
@bucket.instance_variable_set(:@props, {}) # Pretend they are there
|
71
|
+
@backend.should_receive(:set_bucket_props).with(@bucket, { :name => "foo" })
|
123
72
|
@bucket.props = { :name => "foo" }
|
124
73
|
end
|
125
74
|
|
126
|
-
it "should raise an error if an invalid
|
75
|
+
it "should raise an error if an invalid type is given" do
|
127
76
|
lambda { @bucket.props = "blah" }.should raise_error(ArgumentError)
|
128
77
|
end
|
129
|
-
|
130
|
-
it "should escape the bucket name" do
|
131
|
-
@bucket.instance_variable_set :@name, "foo bar"
|
132
|
-
@http.should_receive(:put).with(204, "/riak/","foo%20bar", '{"props":{"n_val":2}}', {"Content-Type" => "application/json"}).and_return({:body => "", :headers => {}})
|
133
|
-
@bucket.props = {:n_val => 2}
|
134
|
-
end
|
135
78
|
end
|
136
79
|
|
137
|
-
describe "fetching
|
138
|
-
|
139
|
-
@
|
140
|
-
@
|
141
|
-
|
142
|
-
|
143
|
-
it "should load the object from the server as a Riak::RObject" do
|
144
|
-
@http.should_receive(:get).with(200, "/riak/","foo", "db", {}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"name":"Riak","company":"Basho"}'})
|
145
|
-
@bucket.get("db").should be_kind_of(Riak::RObject)
|
80
|
+
describe "fetching the bucket properties" do
|
81
|
+
it "should fetch properties on first access" do
|
82
|
+
@bucket.instance_variable_get(:@props).should be_nil
|
83
|
+
@backend.should_receive(:get_bucket_props).with(@bucket).and_return({"name" => "foo"})
|
84
|
+
@bucket.props.should == {"name" => "foo"}
|
146
85
|
end
|
147
86
|
|
148
|
-
it "should
|
149
|
-
@
|
150
|
-
@bucket.
|
87
|
+
it "should memoize fetched properties" do
|
88
|
+
@backend.should_receive(:get_bucket_props).once.with(@bucket).and_return({"name" => "foo"})
|
89
|
+
@bucket.props.should == {"name" => "foo"}
|
90
|
+
@bucket.props.should == {"name" => "foo"}
|
151
91
|
end
|
92
|
+
end
|
152
93
|
|
153
|
-
|
154
|
-
|
155
|
-
@
|
156
|
-
@bucket.get(
|
94
|
+
describe "fetching an object" do
|
95
|
+
it "should fetch the object via the backend" do
|
96
|
+
@backend.should_receive(:fetch_object).with(@bucket, "db", nil).and_return(nil)
|
97
|
+
@bucket.get("db")
|
157
98
|
end
|
158
99
|
|
159
|
-
it "should
|
160
|
-
@
|
161
|
-
@
|
162
|
-
@bucket.get(' bar')
|
100
|
+
it "should use the specified R quroum" do
|
101
|
+
@backend.should_receive(:fetch_object).with(@bucket, "db", 2).and_return(nil)
|
102
|
+
@bucket.get("db", :r => 2)
|
163
103
|
end
|
164
104
|
end
|
165
105
|
|
@@ -173,34 +113,34 @@ describe Riak::Bucket do
|
|
173
113
|
end
|
174
114
|
|
175
115
|
describe "fetching or creating a new object" do
|
176
|
-
before :each do
|
177
|
-
@http = mock("HTTPBackend")
|
178
|
-
@client.stub!(:http).and_return(@http)
|
179
|
-
end
|
180
|
-
|
181
116
|
it "should return the existing object if present" do
|
182
|
-
@
|
183
|
-
|
184
|
-
|
185
|
-
obj.data['name'].should == "Riak"
|
117
|
+
@object = mock("RObject")
|
118
|
+
@backend.should_receive(:fetch_object).with(@bucket,"db", nil).and_return(@object)
|
119
|
+
@bucket.get_or_new('db').should == @object
|
186
120
|
end
|
187
121
|
|
188
122
|
it "should create a new blank object if the key does not exist" do
|
189
|
-
@
|
123
|
+
@backend.should_receive(:fetch_object).and_raise(Riak::FailedRequest.new(:get, 200, 404, {}, "File not found"))
|
190
124
|
obj = @bucket.get_or_new('db')
|
191
125
|
obj.key.should == 'db'
|
192
126
|
obj.data.should be_blank
|
193
127
|
end
|
194
128
|
|
195
129
|
it "should bubble up non-ok non-missing errors" do
|
196
|
-
@
|
130
|
+
@backend.should_receive(:fetch_object).and_raise(Riak::FailedRequest.new(:get, 200, 500, {}, "File not found"))
|
197
131
|
lambda { @bucket.get_or_new('db') }.should raise_error(Riak::FailedRequest)
|
198
132
|
end
|
133
|
+
|
134
|
+
it "should pass along the given R quorum parameter" do
|
135
|
+
@object = mock("RObject")
|
136
|
+
@backend.should_receive(:fetch_object).with(@bucket,"db", "all").and_return(@object)
|
137
|
+
@bucket.get_or_new('db', :r => "all").should == @object
|
138
|
+
end
|
199
139
|
end
|
200
140
|
|
201
141
|
describe "get/set allow_mult property" do
|
202
142
|
before :each do
|
203
|
-
|
143
|
+
@backend.stub!(:get_bucket_props).and_return({"allow_mult" => false})
|
204
144
|
end
|
205
145
|
|
206
146
|
it "should extract the allow_mult property" do
|
@@ -215,7 +155,7 @@ describe Riak::Bucket do
|
|
215
155
|
|
216
156
|
describe "get/set the N value" do
|
217
157
|
before :each do
|
218
|
-
|
158
|
+
@backend.stub!(:get_bucket_props).and_return({"n_val" => 3})
|
219
159
|
end
|
220
160
|
|
221
161
|
it "should extract the N value" do
|
@@ -231,7 +171,7 @@ describe Riak::Bucket do
|
|
231
171
|
[:r, :w, :dw, :rw].each do |q|
|
232
172
|
describe "get/set the default #{q} quorum" do
|
233
173
|
before :each do
|
234
|
-
|
174
|
+
@backend.stub!(:get_bucket_props).and_return({"r" => "quorum", "w" => "quorum", "dw" => "quorum", "rw" => "quorum"})
|
235
175
|
end
|
236
176
|
|
237
177
|
it "should extract the default #{q} quorum" do
|
@@ -245,21 +185,27 @@ describe Riak::Bucket do
|
|
245
185
|
end
|
246
186
|
end
|
247
187
|
|
248
|
-
|
249
188
|
describe "checking whether a key exists" do
|
250
189
|
it "should return true if the object does exist" do
|
251
|
-
@
|
190
|
+
@backend.should_receive(:fetch_object).and_return(mock)
|
252
191
|
@bucket.exists?("foo").should be_true
|
253
192
|
end
|
254
193
|
|
255
194
|
it "should return false if the object doesn't exist" do
|
256
|
-
@
|
195
|
+
@backend.should_receive(:fetch_object).and_raise(Riak::FailedRequest.new(:get, [200,300], 404, {}, "not found"))
|
257
196
|
@bucket.exists?("foo").should be_false
|
258
197
|
end
|
259
198
|
end
|
260
199
|
|
261
|
-
|
262
|
-
|
263
|
-
|
200
|
+
describe "deleting an object" do
|
201
|
+
it "should delete a key from within the bucket" do
|
202
|
+
@backend.should_receive(:delete_object).with(@bucket, "bar", nil)
|
203
|
+
@bucket.delete('bar')
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should use the specified RW quorum" do
|
207
|
+
@backend.should_receive(:delete_object).with(@bucket, "bar", "all")
|
208
|
+
@bucket.delete('bar', :rw => "all")
|
209
|
+
end
|
264
210
|
end
|
265
211
|
end
|
data/spec/riak/client_spec.rb
CHANGED
@@ -112,7 +112,7 @@ describe Riak::Client do
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
it "should allow setting the prefix
|
115
|
+
it "should allow setting the prefix" do
|
116
116
|
@client.should respond_to(:prefix=)
|
117
117
|
@client.prefix = "/another-prefix"
|
118
118
|
@client.prefix.should == "/another-prefix"
|
@@ -165,108 +165,127 @@ describe Riak::Client do
|
|
165
165
|
describe "retrieving a bucket" do
|
166
166
|
before :each do
|
167
167
|
@client = Riak::Client.new
|
168
|
-
@
|
169
|
-
@client.stub!(:
|
170
|
-
@payload = {:headers => {"content-type" => ["application/json"]}, :body => "{}"}
|
171
|
-
@http.stub!(:get).and_return(@payload)
|
168
|
+
@backend = mock("Backend")
|
169
|
+
@client.stub!(:backend).and_return(@backend)
|
172
170
|
end
|
173
171
|
|
174
|
-
it "should
|
175
|
-
@http.should_receive(:get).with(200, "/riak/", "foo", {:keys => false}, {}).and_return(@payload)
|
172
|
+
it "should return a bucket object" do
|
176
173
|
@client.bucket("foo").should be_kind_of(Riak::Bucket)
|
177
174
|
end
|
178
175
|
|
179
|
-
it "should
|
180
|
-
@
|
176
|
+
it "should fetch bucket properties if asked" do
|
177
|
+
@backend.should_receive(:get_bucket_props) {|b| b.name.should == "foo"; {} }
|
178
|
+
@client.bucket("foo", :props => true)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should fetch keys if asked" do
|
182
|
+
@backend.should_receive(:list_keys) {|b| b.name.should == "foo"; ["bar"] }
|
181
183
|
@client.bucket("foo", :keys => true)
|
182
184
|
end
|
183
185
|
|
184
|
-
|
185
|
-
|
186
|
-
@
|
186
|
+
|
187
|
+
it "should memoize bucket parameters" do
|
188
|
+
@bucket = mock("Bucket")
|
189
|
+
Riak::Bucket.should_receive(:new).with(@client, "baz").once.and_return(@bucket)
|
190
|
+
@client.bucket("baz").should == @bucket
|
191
|
+
@client.bucket("baz").should == @bucket
|
187
192
|
end
|
188
193
|
end
|
189
194
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
195
|
+
it "should list buckets" do
|
196
|
+
@client = Riak::Client.new
|
197
|
+
@backend = mock("Backend")
|
198
|
+
@client.stub!(:backend).and_return(@backend)
|
199
|
+
@backend.should_receive(:list_buckets).and_return(%w{test test2})
|
200
|
+
buckets = @client.buckets
|
201
|
+
buckets.should have(2).items
|
202
|
+
buckets.should be_all {|b| b.is_a?(Riak::Bucket) }
|
203
|
+
buckets[0].name.should == "test"
|
204
|
+
buckets[1].name.should == "test2"
|
205
|
+
end
|
196
206
|
|
197
|
-
|
198
|
-
|
199
|
-
|
207
|
+
describe "Luwak (large-files) support" do
|
208
|
+
describe "storing a file" do
|
209
|
+
before :each do
|
210
|
+
@client = Riak::Client.new
|
211
|
+
@http = mock(Riak::Client::HTTPBackend)
|
212
|
+
@client.stub!(:http).and_return(@http)
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should store the file in Luwak and return the key/filename when no filename is given" do
|
216
|
+
@http.should_receive(:post).with(201, "/luwak", anything, {"Content-Type" => "text/plain"}).and_return(:code => 201, :headers => {"location" => ["/luwak/123456789"]})
|
217
|
+
@client.store_file("text/plain", "Hello, world").should == "123456789"
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should store the file in Luwak and return the key/filename when the filename is given" do
|
221
|
+
@http.should_receive(:put).with(204, "/luwak", "greeting.txt", anything, {"Content-Type" => "text/plain"}).and_return(:code => 204, :headers => {})
|
222
|
+
@client.store_file("greeting.txt", "text/plain", "Hello, world").should == "greeting.txt"
|
223
|
+
end
|
200
224
|
end
|
201
225
|
|
202
|
-
|
203
|
-
|
204
|
-
|
226
|
+
describe "retrieving a file" do
|
227
|
+
before :each do
|
228
|
+
@client = Riak::Client.new
|
229
|
+
@http = mock(Riak::Client::HTTPBackend)
|
230
|
+
@client.stub!(:http).and_return(@http)
|
231
|
+
@http.should_receive(:get).with(200, "/luwak", "greeting.txt").and_yield("Hello,").and_yield(" world!").and_return({:code => 200, :headers => {"content-type" => ["text/plain"]}})
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should stream the data to a temporary file" do
|
235
|
+
file = @client.get_file("greeting.txt")
|
236
|
+
file.open {|f| f.read.should == "Hello, world!" }
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should stream the data through the given block, returning nil" do
|
240
|
+
string = ""
|
241
|
+
result = @client.get_file("greeting.txt"){|chunk| string << chunk }
|
242
|
+
result.should be_nil
|
243
|
+
string.should == "Hello, world!"
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should expose the original key and content-type on the temporary file" do
|
247
|
+
file = @client.get_file("greeting.txt")
|
248
|
+
file.content_type.should == "text/plain"
|
249
|
+
file.original_filename.should == "greeting.txt"
|
250
|
+
end
|
205
251
|
end
|
206
|
-
end
|
207
252
|
|
208
|
-
|
209
|
-
before :each do
|
253
|
+
it "should delete a file" do
|
210
254
|
@client = Riak::Client.new
|
211
255
|
@http = mock(Riak::Client::HTTPBackend)
|
212
256
|
@client.stub!(:http).and_return(@http)
|
213
|
-
@http.should_receive(:
|
257
|
+
@http.should_receive(:delete).with([204,404], "/luwak", "greeting.txt")
|
258
|
+
@client.delete_file("greeting.txt")
|
214
259
|
end
|
215
260
|
|
216
|
-
it "should
|
217
|
-
|
218
|
-
|
261
|
+
it "should return true if the file exists" do
|
262
|
+
@client = Riak::Client.new
|
263
|
+
@client.http.should_receive(:head).and_return(:code => 200)
|
264
|
+
@client.file_exists?("foo").should be_true
|
219
265
|
end
|
220
266
|
|
221
|
-
it "should
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
string.should == "Hello, world!"
|
267
|
+
it "should return false if the file doesn't exist" do
|
268
|
+
@client = Riak::Client.new
|
269
|
+
@client.http.should_receive(:head).and_return(:code => 404)
|
270
|
+
@client.file_exists?("foo").should be_false
|
226
271
|
end
|
227
272
|
|
228
|
-
it "should
|
229
|
-
|
230
|
-
|
231
|
-
|
273
|
+
it "should escape the filename when storing, retrieving or deleting files" do
|
274
|
+
@client = Riak::Client.new
|
275
|
+
@http = mock(Riak::Client::HTTPBackend)
|
276
|
+
@client.stub!(:http).and_return(@http)
|
277
|
+
# Delete escapes keys
|
278
|
+
@http.should_receive(:delete).with([204,404], "/luwak", "docs%2FA%20Big%20PDF.pdf")
|
279
|
+
@client.delete_file("docs/A Big PDF.pdf")
|
280
|
+
# Get escapes keys
|
281
|
+
@http.should_receive(:get).with(200, "/luwak", "docs%2FA%20Big%20PDF.pdf").and_yield("foo").and_return(:headers => {"content-type" => ["text/plain"]}, :code => 200)
|
282
|
+
@client.get_file("docs/A Big PDF.pdf")
|
283
|
+
# Streamed get escapes keys
|
284
|
+
@http.should_receive(:get).with(200, "/luwak", "docs%2FA%20Big%20PDF.pdf").and_yield("foo").and_return(:headers => {"content-type" => ["text/plain"]}, :code => 200)
|
285
|
+
@client.get_file("docs/A Big PDF.pdf"){|chunk| chunk }
|
286
|
+
# Put escapes keys
|
287
|
+
@http.should_receive(:put).with(204, "/luwak", "docs%2FA%20Big%20PDF.pdf", "foo", {"Content-Type" => "text/plain"})
|
288
|
+
@client.store_file("docs/A Big PDF.pdf", "text/plain", "foo")
|
232
289
|
end
|
233
290
|
end
|
234
|
-
|
235
|
-
it "should delete a file" do
|
236
|
-
@client = Riak::Client.new
|
237
|
-
@http = mock(Riak::Client::HTTPBackend)
|
238
|
-
@client.stub!(:http).and_return(@http)
|
239
|
-
@http.should_receive(:delete).with([204,404], "/luwak", "greeting.txt")
|
240
|
-
@client.delete_file("greeting.txt")
|
241
|
-
end
|
242
|
-
|
243
|
-
it "should return true if the file exists" do
|
244
|
-
@client = Riak::Client.new
|
245
|
-
@client.http.should_receive(:head).and_return(:code => 200)
|
246
|
-
@client.file_exists?("foo").should be_true
|
247
|
-
end
|
248
|
-
|
249
|
-
it "should return false if the file doesn't exist" do
|
250
|
-
@client = Riak::Client.new
|
251
|
-
@client.http.should_receive(:head).and_return(:code => 404)
|
252
|
-
@client.file_exists?("foo").should be_false
|
253
|
-
end
|
254
|
-
|
255
|
-
it "should escape the filename when storing, retrieving or deleting files" do
|
256
|
-
@client = Riak::Client.new
|
257
|
-
@http = mock(Riak::Client::HTTPBackend)
|
258
|
-
@client.stub!(:http).and_return(@http)
|
259
|
-
# Delete escapes keys
|
260
|
-
@http.should_receive(:delete).with([204,404], "/luwak", "docs%2FA%20Big%20PDF.pdf")
|
261
|
-
@client.delete_file("docs/A Big PDF.pdf")
|
262
|
-
# Get escapes keys
|
263
|
-
@http.should_receive(:get).with(200, "/luwak", "docs%2FA%20Big%20PDF.pdf").and_yield("foo").and_return(:headers => {"content-type" => ["text/plain"]}, :code => 200)
|
264
|
-
@client.get_file("docs/A Big PDF.pdf")
|
265
|
-
# Streamed get escapes keys
|
266
|
-
@http.should_receive(:get).with(200, "/luwak", "docs%2FA%20Big%20PDF.pdf").and_yield("foo").and_return(:headers => {"content-type" => ["text/plain"]}, :code => 200)
|
267
|
-
@client.get_file("docs/A Big PDF.pdf"){|chunk| chunk }
|
268
|
-
# Put escapes keys
|
269
|
-
@http.should_receive(:put).with(204, "/luwak", "docs%2FA%20Big%20PDF.pdf", "foo", {"Content-Type" => "text/plain"})
|
270
|
-
@client.store_file("docs/A Big PDF.pdf", "text/plain", "foo")
|
271
|
-
end
|
272
291
|
end
|