riak-client 1.0.0.beta → 1.0.0
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/.gitignore +7 -4
- data/Gemfile +12 -17
- data/Guardfile +1 -1
- data/LICENSE +16 -0
- data/README.markdown +178 -0
- data/RELEASE_NOTES.md +99 -0
- data/Rakefile +25 -1
- data/erl_src/riak_kv_test014_backend.beam +0 -0
- data/erl_src/riak_kv_test014_backend.erl +189 -0
- data/erl_src/riak_kv_test_backend.beam +0 -0
- data/erl_src/riak_kv_test_backend.erl +37 -19
- data/lib/riak/client.rb +322 -272
- data/lib/riak/client/beefcake_protobuffs_backend.rb +6 -10
- data/lib/riak/client/decaying.rb +28 -0
- data/lib/riak/client/excon_backend.rb +27 -11
- data/lib/riak/client/http_backend.rb +71 -2
- data/lib/riak/client/http_backend/configuration.rb +17 -3
- data/lib/riak/client/http_backend/transport_methods.rb +3 -3
- data/lib/riak/client/net_http_backend.rb +18 -14
- data/lib/riak/client/node.rb +111 -0
- data/lib/riak/client/pool.rb +180 -0
- data/lib/riak/client/protobuffs_backend.rb +15 -5
- data/lib/riak/client/search.rb +9 -3
- data/lib/riak/link.rb +5 -7
- data/lib/riak/locale/en.yml +1 -0
- data/lib/riak/node/configuration.rb +1 -0
- data/lib/riak/node/defaults.rb +19 -6
- data/lib/riak/node/generation.rb +9 -2
- data/lib/riak/node/log.rb +2 -2
- data/lib/riak/node/version.rb +22 -16
- data/lib/riak/robject.rb +19 -3
- data/lib/riak/serializers.rb +1 -1
- data/lib/riak/test_server.rb +10 -2
- data/lib/riak/version.rb +1 -1
- data/riak-client.gemspec +3 -3
- data/spec/failover/failover.rb +59 -0
- data/spec/integration/riak/http_backends_spec.rb +2 -2
- data/spec/integration/riak/node_spec.rb +16 -24
- data/spec/integration/riak/protobuffs_backends_spec.rb +1 -1
- data/spec/integration/riak/test_server_spec.rb +4 -3
- data/spec/integration/riak/threading_spec.rb +193 -0
- data/spec/riak/beefcake_protobuffs_backend/object_methods_spec.rb +23 -0
- data/spec/riak/beefcake_protobuffs_backend_spec.rb +4 -2
- data/spec/riak/bucket_spec.rb +2 -1
- data/spec/riak/client_spec.rb +80 -181
- data/spec/riak/excon_backend_spec.rb +3 -2
- data/spec/riak/http_backend/configuration_spec.rb +37 -5
- data/spec/riak/http_backend/object_methods_spec.rb +1 -1
- data/spec/riak/http_backend/transport_methods_spec.rb +2 -2
- data/spec/riak/http_backend_spec.rb +53 -3
- data/spec/riak/map_reduce_spec.rb +1 -1
- data/spec/riak/net_http_backend_spec.rb +1 -2
- data/spec/riak/node_spec.rb +173 -0
- data/spec/riak/pool_spec.rb +306 -0
- data/spec/riak/robject_spec.rb +8 -4
- data/spec/riak/search_spec.rb +66 -15
- data/spec/riak/serializers_spec.rb +12 -1
- data/spec/spec_helper.rb +9 -1
- data/spec/support/http_backend_implementation_examples.rb +6 -2
- data/spec/support/sometimes.rb +46 -0
- data/spec/support/test_server.rb +50 -19
- data/spec/support/unified_backend_examples.rb +11 -10
- data/spec/support/version_filter.rb +14 -0
- metadata +40 -29
- data/lib/active_support/cache/riak_store.rb +0 -2
- data/lib/riak/cache_store.rb +0 -84
- data/lib/riak/client/pump.rb +0 -30
- data/lib/riak/util/fiber1.8.rb +0 -48
- data/spec/integration/riak/cache_store_spec.rb +0 -129
data/lib/riak/robject.rb
CHANGED
@@ -50,14 +50,29 @@ module Riak
|
|
50
50
|
# @see http://wiki.basho.com/display/RIAK/REST+API#RESTAPI-Storeaneworexistingobjectwithakey Riak Rest API Docs
|
51
51
|
attr_accessor :prevent_stale_writes
|
52
52
|
|
53
|
+
# Defines a callback to be invoked when there is conflict.
|
54
|
+
#
|
55
|
+
# @yield The conflict callback.
|
56
|
+
# @yieldparam [RObject] robject The conflicted RObject
|
57
|
+
# @yieldreturn [RObject, nil] Either the resolved RObject or nil if your
|
58
|
+
# callback cannot resolve it. The next registered
|
59
|
+
# callback will be given the chance to resolve it.
|
60
|
+
#
|
61
|
+
# @note Ripple registers its own document-level conflict handler, so if you're
|
62
|
+
# using ripple, you will probably want to use that instead.
|
53
63
|
def self.on_conflict(&conflict_hook)
|
54
64
|
on_conflict_hooks << conflict_hook
|
55
65
|
end
|
56
66
|
|
67
|
+
# @return [Array<Proc>] the list of registered conflict callbacks.
|
57
68
|
def self.on_conflict_hooks
|
58
69
|
@on_conflict_hooks ||= []
|
59
70
|
end
|
60
71
|
|
72
|
+
# Attempts to resolve conflict using the registered conflict callbacks.
|
73
|
+
#
|
74
|
+
# @return [RObject] the RObject
|
75
|
+
# @note There is no guarantee the returned RObject will have been resolved
|
61
76
|
def attempt_conflict_resolution
|
62
77
|
return self unless conflict?
|
63
78
|
|
@@ -195,9 +210,10 @@ module Riak
|
|
195
210
|
|
196
211
|
# Returns sibling objects when in conflict.
|
197
212
|
# @return [Array<RObject>] an array of conflicting sibling objects for this key
|
198
|
-
# @return [self]
|
213
|
+
# @return [Array<self>] a single-element array containing object when not
|
214
|
+
# in conflict
|
199
215
|
def siblings
|
200
|
-
return self unless conflict?
|
216
|
+
return [self] unless conflict?
|
201
217
|
@siblings
|
202
218
|
end
|
203
219
|
|
@@ -244,7 +260,7 @@ module Riak
|
|
244
260
|
# @param [Array<Hash,WalkSpec>] link specifications for the query
|
245
261
|
def walk(*params)
|
246
262
|
specs = WalkSpec.normalize(*params)
|
247
|
-
@bucket.client.
|
263
|
+
@bucket.client.link_walk(self, specs)
|
248
264
|
end
|
249
265
|
|
250
266
|
# Converts the object to a link suitable for linking other objects
|
data/lib/riak/serializers.rb
CHANGED
@@ -22,7 +22,7 @@ module Riak
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def serializer_for(content_type)
|
25
|
-
serializers.fetch(content_type) do
|
25
|
+
serializers.fetch(content_type[/^[^;\s]+/]) do
|
26
26
|
raise NotImplementedError.new(t('serializer_not_implemented', :content_type => content_type.inspect))
|
27
27
|
end
|
28
28
|
end
|
data/lib/riak/test_server.rb
CHANGED
@@ -17,7 +17,6 @@ module Riak
|
|
17
17
|
configuration[:env] ||= {}
|
18
18
|
configuration[:env][:riak_kv] ||= {}
|
19
19
|
(configuration[:env][:riak_kv][:add_paths] ||= []) << File.expand_path("../../../erl_src", __FILE__)
|
20
|
-
configuration[:env][:riak_kv][:storage_backend] = :riak_kv_test_backend
|
21
20
|
configuration[:env][:riak_search] ||= {}
|
22
21
|
configuration[:env][:riak_search][:search_backend] = :riak_search_test_backend
|
23
22
|
super configuration
|
@@ -52,7 +51,7 @@ module Riak
|
|
52
51
|
def drop
|
53
52
|
begin
|
54
53
|
maybe_attach
|
55
|
-
@console.command "
|
54
|
+
@console.command "#{kv_backend}:reset()."
|
56
55
|
@console.command "riak_search_test_backend:reset()."
|
57
56
|
rescue IOError
|
58
57
|
retry
|
@@ -71,5 +70,14 @@ module Riak
|
|
71
70
|
def open?
|
72
71
|
@console && @console.open?
|
73
72
|
end
|
73
|
+
|
74
|
+
def configure_data
|
75
|
+
super
|
76
|
+
if version < "1.0.0"
|
77
|
+
env[:riak_kv][:storage_backend] = :riak_kv_test014_backend
|
78
|
+
else
|
79
|
+
env[:riak_kv][:storage_backend] = :riak_kv_test_backend
|
80
|
+
end
|
81
|
+
end
|
74
82
|
end
|
75
83
|
end
|
data/lib/riak/version.rb
CHANGED
data/riak-client.gemspec
CHANGED
@@ -8,15 +8,15 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.summary = %Q{riak-client is a rich client for Riak, the distributed database by Basho.}
|
9
9
|
gem.description = %Q{riak-client is a rich client for Riak, the distributed database by Basho. It supports the full HTTP and Protocol Buffers interfaces including storage operations, bucket configuration, link-walking, secondary indexes and map-reduce.}
|
10
10
|
gem.email = ["sean@basho.com"]
|
11
|
-
gem.homepage = "http://
|
11
|
+
gem.homepage = "http://github.com/basho/riak-ruby-client"
|
12
12
|
gem.authors = ["Sean Cribbs"]
|
13
13
|
|
14
14
|
# Deps
|
15
|
-
gem.add_development_dependency "rspec", "~>2.
|
15
|
+
gem.add_development_dependency "rspec", "~>2.8.0"
|
16
16
|
gem.add_development_dependency "fakeweb", ">=1.2"
|
17
17
|
gem.add_development_dependency "rack", ">=1.0"
|
18
18
|
gem.add_development_dependency "excon", "~>0.6.1"
|
19
|
-
gem.add_development_dependency 'rake'
|
19
|
+
gem.add_development_dependency 'rake'
|
20
20
|
gem.add_runtime_dependency "i18n", ">=0.4.0"
|
21
21
|
gem.add_runtime_dependency "builder", ">= 2.1.2"
|
22
22
|
gem.add_runtime_dependency "beefcake", "~>0.3.7"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
2
|
+
require 'riak'
|
3
|
+
|
4
|
+
# This is not a formal spec yet. It's designed to be run agains a local dev
|
5
|
+
# cluster while you bring nodes up and down.
|
6
|
+
[
|
7
|
+
{:protocol => 'pbc', :protobuffs_backend => :Beefcake},
|
8
|
+
{:protocol => 'http', :http_backend => :NetHTTP},
|
9
|
+
{:protocol => 'http', :http_backend => :Excon}
|
10
|
+
].each do |opts|
|
11
|
+
@client = Riak::Client.new(
|
12
|
+
{
|
13
|
+
:nodes => (1..3).map { |i|
|
14
|
+
{
|
15
|
+
:http_port => 8090 + i,
|
16
|
+
:pb_port => 8080 + i
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}.merge(opts)
|
20
|
+
)
|
21
|
+
|
22
|
+
errors = []
|
23
|
+
p opts
|
24
|
+
|
25
|
+
n = 10
|
26
|
+
c = 1000
|
27
|
+
|
28
|
+
(0...n).map do |t|
|
29
|
+
Thread.new do
|
30
|
+
# Generate a stream of put reqs. Put a . for each success, an X for
|
31
|
+
# each failure.
|
32
|
+
c.times do |i|
|
33
|
+
begin
|
34
|
+
o = @client['test'].new("#{t}:#{i}")
|
35
|
+
o.content_type = 'text/plain'
|
36
|
+
o.data = i.to_s
|
37
|
+
o.store
|
38
|
+
o2 = @client['test'].get("#{t}:#{i}")
|
39
|
+
o2.data == i.to_s or raise "wrong data"
|
40
|
+
print '.'
|
41
|
+
rescue => e
|
42
|
+
print 'X'
|
43
|
+
errors << e
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end.each do |thread|
|
48
|
+
thread.join
|
49
|
+
end
|
50
|
+
|
51
|
+
# Put errors
|
52
|
+
puts
|
53
|
+
errors.each do |e|
|
54
|
+
puts e.inspect
|
55
|
+
puts e.backtrace.map { |x| " #{x}" }.join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
puts "\n\n"
|
59
|
+
end
|
@@ -11,7 +11,7 @@ describe "HTTP" do
|
|
11
11
|
if bklass.configured?
|
12
12
|
describe klass.to_s do
|
13
13
|
before do
|
14
|
-
@backend = bklass.new(@client)
|
14
|
+
@backend = bklass.new(@client, @client.node)
|
15
15
|
end
|
16
16
|
|
17
17
|
it_should_behave_like "Unified backend API"
|
@@ -34,7 +34,7 @@ describe "HTTP" do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
describe 'NetHTTPBackend' do
|
37
|
-
subject { Riak::Client::NetHTTPBackend.new(@client) }
|
37
|
+
subject { Riak::Client::NetHTTPBackend.new(@client, @client.node) }
|
38
38
|
let(:file) { File.open(__FILE__) }
|
39
39
|
let(:sized) { Reader.new(["foo", "bar", "baz"]) }
|
40
40
|
let(:sizeless) { SizelessReader.new(["foo", "bar", "baz"]) }
|
@@ -4,34 +4,26 @@ require 'yaml'
|
|
4
4
|
|
5
5
|
describe Riak::Node, :test_server => false, :slow => true do
|
6
6
|
let(:test_server_config){ YAML.load_file("spec/support/test_server.yml") }
|
7
|
-
|
8
|
-
|
9
|
-
after
|
7
|
+
let(:node){ described_class.new(:root => ".ripplenode", :source => test_server_config['source']) }
|
8
|
+
subject { node }
|
9
|
+
after { node.stop if node.started? }
|
10
|
+
after(:all) { node.destroy }
|
11
|
+
|
12
|
+
context "finding the base_dir and version" do
|
13
|
+
its(:base_dir) { should be_directory }
|
14
|
+
its(:version) { should match /^\d+.\d+.\d+$/ }
|
15
|
+
|
16
|
+
context "when the base directory is missing" do
|
17
|
+
before { Pathname.any_instance.stub(:each_line).and_return([]) }
|
18
|
+
its(:base_dir) { should be_nil }
|
19
|
+
its(:version) { should be_nil }
|
20
|
+
end
|
21
|
+
end
|
10
22
|
|
11
23
|
context "creation" do
|
12
24
|
before { subject.create }
|
13
25
|
after { subject.destroy }
|
14
26
|
|
15
|
-
describe "finding the base_dir and version" do
|
16
|
-
it "should return a valid directory for base_dir" do
|
17
|
-
subject.base_dir.should be_exist
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should read a version from the releases directory" do
|
21
|
-
subject.version.should match /\d+.\d+.\d+/
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should return nil for base_dir if RUNNER_BASE_DIR is not found" do
|
25
|
-
Pathname.any_instance.stub(:readlines).and_return([])
|
26
|
-
subject.base_dir.should be_nil
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should return nil for version if base_dir is nil" do
|
30
|
-
Pathname.any_instance.stub(:readlines).and_return([])
|
31
|
-
subject.version.should be_nil
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
27
|
describe "generating the manifest" do
|
36
28
|
it "should store the configuration manifest in the node directory" do
|
37
29
|
(subject.root + '.node.yml').should be_exist
|
@@ -175,7 +167,7 @@ describe Riak::Node, :test_server => false, :slow => true do
|
|
175
167
|
it "should read the console log" do
|
176
168
|
if subject.version >= "1.0.0"
|
177
169
|
subject.read_console_log(:debug, :info, :notice).should_not be_empty
|
178
|
-
subject.read_console_log(
|
170
|
+
subject.read_console_log('debug'..'emergency').should_not be_empty
|
179
171
|
subject.read_console_log(:info).should_not be_empty
|
180
172
|
subject.read_console_log(:foo).should be_empty
|
181
173
|
end
|
@@ -12,9 +12,10 @@ describe Riak::TestServer do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should use the KV test backend" do
|
15
|
-
subject.
|
16
|
-
subject.
|
17
|
-
|
15
|
+
backend = subject.version < "1.0.0" ? :riak_kv_test014_backend : :riak_kv_test_backend
|
16
|
+
subject.kv_backend.should == backend
|
17
|
+
subject.env[:riak_kv][:storage_backend].should == backend
|
18
|
+
app_config.should include("{storage_backend, #{backend}}")
|
18
19
|
end
|
19
20
|
|
20
21
|
it "should use the Search test backend" do
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Multithreaded client", :test_server => true do
|
4
|
+
class Synchronizer
|
5
|
+
def initialize(n)
|
6
|
+
@mutex = Mutex.new
|
7
|
+
@n = n
|
8
|
+
@waiting = Set.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def sync
|
12
|
+
stop = false
|
13
|
+
@mutex.synchronize do
|
14
|
+
@waiting << Thread.current
|
15
|
+
|
16
|
+
if @waiting.size >= @n
|
17
|
+
# All threads are waiting.
|
18
|
+
@waiting.each do |t|
|
19
|
+
t.run
|
20
|
+
end
|
21
|
+
else
|
22
|
+
stop = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if stop
|
27
|
+
Thread.stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def threads(n, opts = {})
|
33
|
+
if opts[:synchronize]
|
34
|
+
s1 = Synchronizer.new n
|
35
|
+
s2 = Synchronizer.new n
|
36
|
+
end
|
37
|
+
|
38
|
+
threads = (0...n).map do |i|
|
39
|
+
Thread.new do
|
40
|
+
if opts[:synchronize]
|
41
|
+
s1.sync
|
42
|
+
end
|
43
|
+
|
44
|
+
yield i
|
45
|
+
|
46
|
+
if opts[:synchronize]
|
47
|
+
s2.sync
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
threads.each do |t|
|
53
|
+
t.join
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
[
|
58
|
+
{:protocol => 'pbc', :protobuffs_backend => :Beefcake},
|
59
|
+
{:protocol => 'http', :http_backend => :NetHTTP},
|
60
|
+
{:protocol => 'http', :http_backend => :Excon}
|
61
|
+
].each do |opts|
|
62
|
+
describe opts.inspect do
|
63
|
+
before do
|
64
|
+
@pb_port ||= $test_server.pb_port
|
65
|
+
@http_port ||= $test_server.http_port
|
66
|
+
@client = Riak::Client.new({
|
67
|
+
:pb_port => @pb_port,
|
68
|
+
:http_port => @http_port
|
69
|
+
}.merge(opts))
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should get in parallel' do
|
73
|
+
data = "the gun is good"
|
74
|
+
ro = @client['test'].new('test')
|
75
|
+
ro.content_type = "application/json"
|
76
|
+
ro.data = [data]
|
77
|
+
ro.store
|
78
|
+
|
79
|
+
threads 10, :synchronize => true do
|
80
|
+
x = @client['test']['test']
|
81
|
+
x.content_type.should == "application/json"
|
82
|
+
x.data.should == [data]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should put in parallel' do
|
87
|
+
data = "the tabernacle is indestructible and everlasting"
|
88
|
+
|
89
|
+
n = 10
|
90
|
+
threads n, :synchronize => true do |i|
|
91
|
+
x = @client['test'].new("test-#{i}")
|
92
|
+
x.content_type = "application/json"
|
93
|
+
x.data = ["#{data}-#{i}"]
|
94
|
+
x.store
|
95
|
+
end
|
96
|
+
|
97
|
+
(0...n).each do |i|
|
98
|
+
read = @client['test']["test-#{i}"]
|
99
|
+
read.content_type.should == "application/json"
|
100
|
+
read.data.should == ["#{data}-#{i}"]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# This is a 1.0+ spec because putting with the same client ID
|
105
|
+
# will not create siblings on 0.14 in the same way. This will
|
106
|
+
# also likely fail for nodes with vnode_vclocks = false.
|
107
|
+
it 'should put conflicts in parallel', :version => "1.0.0" do
|
108
|
+
@client['test'].allow_mult = true
|
109
|
+
@client['test'].allow_mult.should == true
|
110
|
+
|
111
|
+
init = @client['test'].new('test')
|
112
|
+
init.content_type = "application/json"
|
113
|
+
init.data = ''
|
114
|
+
init.store
|
115
|
+
|
116
|
+
# Create conflicting writes
|
117
|
+
n = 10
|
118
|
+
s = Synchronizer.new n
|
119
|
+
threads n, :synchronize => true do |i|
|
120
|
+
x = @client['test']["test"]
|
121
|
+
s.sync
|
122
|
+
x.data = [i]
|
123
|
+
x.store
|
124
|
+
end
|
125
|
+
|
126
|
+
read = @client['test']["test"]
|
127
|
+
read.conflict?.should == true
|
128
|
+
read.siblings.map do |sibling|
|
129
|
+
sibling.data.first
|
130
|
+
end.to_set.should == (0...n).to_set
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should list-keys and get in parallel', :slow => true do
|
134
|
+
count = 100
|
135
|
+
threads = 2
|
136
|
+
|
137
|
+
# Create items
|
138
|
+
count.times do |i|
|
139
|
+
o = @client['test'].new("#{i}")
|
140
|
+
o.content_type = 'application/json'
|
141
|
+
o.data = [i]
|
142
|
+
o.store
|
143
|
+
end
|
144
|
+
|
145
|
+
threads(threads) do
|
146
|
+
set = Set.new
|
147
|
+
@client['test'].keys do |stream|
|
148
|
+
stream.each do |key|
|
149
|
+
set.merge @client['test'][key].data
|
150
|
+
end
|
151
|
+
end
|
152
|
+
set.should == (0...count).to_set
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
sometimes 'should mapreduce in parallel' do
|
157
|
+
if ("1.0.0"..."1.1.0").include?(test_server.version)
|
158
|
+
# On a fresh node, this module might not have been loaded yet
|
159
|
+
# and the mapred test exposes a race condition in riak_pipe_v
|
160
|
+
# when verifying function validity. This race condition is
|
161
|
+
# fixed in 1.1.
|
162
|
+
test_server.with_console do |console|
|
163
|
+
console.command 'code:load(riak_kv_pipe_get), ok.'
|
164
|
+
console.command 'code:load(riak_kv_mrc_map), ok.'
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
count = 10
|
169
|
+
threads = 10
|
170
|
+
|
171
|
+
# Create items
|
172
|
+
count.times do |i|
|
173
|
+
o = @client['test'].new("#{i}")
|
174
|
+
o.content_type = 'application/json'
|
175
|
+
o.data = i
|
176
|
+
o.store
|
177
|
+
end
|
178
|
+
|
179
|
+
# Ze mapreduce
|
180
|
+
threads(threads) do
|
181
|
+
# Mapreduce
|
182
|
+
(0...count).inject(Riak::MapReduce.new(@client)) do |mr, i|
|
183
|
+
mr.add('test', i.to_s)
|
184
|
+
end.map(%{function(v) {
|
185
|
+
return [v.key];
|
186
|
+
}}, :keep => true).run.map do |s|
|
187
|
+
s.to_i
|
188
|
+
end.to_set.should == (0...count).to_set
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|