riak-client 1.1.1 → 1.2.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/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
  gem 'bundler'
@@ -9,7 +9,7 @@ group :guard do
9
9
  gem 'rb-fsevent'
10
10
  gem 'growl'
11
11
  end
12
-
12
+
13
13
  platforms :mri do
14
14
  gem 'yajl-ruby'
15
15
  end
@@ -1,5 +1,27 @@
1
1
  # Riak Ruby Client Release Notes
2
2
 
3
+ ## 1.2.0 Feature Release - 2013-05-15
4
+
5
+ Release 1.2.0 adds support for Riak 1.3 and fixes a number of bugs.
6
+
7
+ Features:
8
+
9
+ * The "clear bucket properties" feature has been added. This resets
10
+ modified bucket properties to the defaults on Riak 1.3+ clusters.
11
+ * Anonymous "strfun" MapReduce functions written in Erlang can now be
12
+ sent from the client, if they are enabled on the server-side.
13
+
14
+ Bugfixes:
15
+
16
+ * The WalkSpec class now properly includes the Translation module.
17
+ * The Protocol Buffers transport now extracts the bucket name before
18
+ submitting secondary index queries.
19
+ * Search query results returned over PBC are assumed to be UTF-8
20
+ encoded.
21
+ * The newer Excon API is now supported (>= 0.19.0).
22
+ * When enabling the search commit hook, the 'precommit' property will
23
+ now be checked more safely.
24
+
3
25
  ## 1.1.1 Patch/Bugfix Release - 2013-01-10
4
26
 
5
27
  Release 1.1.1 fixes a minor bug with Net::HTTP on Ruby 1.8.7 with
@@ -78,6 +78,15 @@ module Riak
78
78
  end
79
79
  alias :properties :props
80
80
 
81
+ # Clears bucket properties, reverting them to the defaults.
82
+ # @return [true, false] whether the properties were cleared
83
+ # @since Riak 1.3
84
+ def clear_props
85
+ @props = nil
86
+ @client.clear_bucket_props(self)
87
+ end
88
+ alias :clear_properties :clear_props
89
+
81
90
  # Retrieve an object from within the bucket.
82
91
  # @param [String] key the key of the object to retrieve
83
92
  # @param [Hash] options query parameters for the request
@@ -205,7 +214,7 @@ module Riak
205
214
  # riak_search.
206
215
  # @return [true,false] whether the bucket includes the search indexing hook
207
216
  def is_indexed?
208
- props['search'] == true || props['precommit'].include?(SEARCH_PRECOMMIT_HOOK)
217
+ props['search'] == true || (props.has_key?('precommit') && props['precommit'].include?(SEARCH_PRECOMMIT_HOOK))
209
218
  end
210
219
 
211
220
  # @return [String] a representation suitable for IRB and debugging output
@@ -469,6 +469,13 @@ module Riak
469
469
  end
470
470
  end
471
471
 
472
+ # Clears the properties on a bucket. See Bucket#clear_props
473
+ def clear_bucket_props(bucket)
474
+ http do |b|
475
+ b.clear_bucket_props(bucket)
476
+ end
477
+ end
478
+
472
479
  # Enables or disables SSL on all nodes, for HTTP backends.
473
480
  def ssl=(value)
474
481
  @nodes.each do |node|
@@ -126,6 +126,7 @@ module Riak
126
126
 
127
127
  def get_index(bucket, index, query)
128
128
  return super unless pb_indexes?
129
+ bucket = bucket.name if Bucket === bucket
129
130
  if Range === query
130
131
  options = {
131
132
  :qtype => RpbIndexReq::IndexQueryType::RANGE,
@@ -218,7 +219,12 @@ module Riak
218
219
  end
219
220
 
220
221
  def decode_doc(doc)
221
- Hash[doc.properties.map {|p| [ p.key, p.value ] }]
222
+ Hash[doc.properties.map {|p| [ force_utf8(p.key), force_utf8(p.value) ] }]
223
+ end
224
+
225
+ def force_utf8(str)
226
+ # Search returns strings that should always be valid UTF-8
227
+ ObjectMethods::ENCODING ? str.force_encoding('UTF-8') : str
222
228
  end
223
229
  end
224
230
  end
@@ -150,12 +150,22 @@ module Riak
150
150
  end
151
151
 
152
152
  def connection
153
- @connection ||= Excon::Connection.new(
154
- root_uri.to_s,
155
- :read_timeout => self.class.read_timeout,
153
+ @connection ||= new_connection
154
+ end
155
+
156
+ def new_connection
157
+ params = { :read_timeout => self.class.read_timeout,
156
158
  :write_timeout => self.class.write_timeout,
157
- :connect_timeout => self.class.connect_timeout
158
- )
159
+ :connect_timeout => self.class.connect_timeout }
160
+ args = [ params ]
161
+ if self.class.minimum_version?("0.19.0")
162
+ params.merge!(:scheme => root_uri.scheme,
163
+ :host => root_uri.host,
164
+ :port => root_uri.port)
165
+ else
166
+ args.unshift root_uri.to_s
167
+ end
168
+ Excon::Connection.new(*args)
159
169
  end
160
170
  end
161
171
  end
@@ -13,7 +13,8 @@ module Riak
13
13
  VERSION = {
14
14
  1 => Gem::Version.new("1.0.0"),
15
15
  1.1 => Gem::Version.new("1.1.0"),
16
- 1.2 => Gem::Version.new("1.2.0")
16
+ 1.2 => Gem::Version.new("1.2.0"),
17
+ 1.3 => Gem::Version.new("1.3.0")
17
18
  }.freeze
18
19
 
19
20
  # @return [String] the version of the Riak node
@@ -71,6 +72,12 @@ module Riak
71
72
  at_least? VERSION[1]
72
73
  end
73
74
 
75
+ # @return [true,false] whether bucket properties can be cleared
76
+ # (reset to defaults) over HTTP
77
+ def http_props_clearable?
78
+ at_least? VERSION[1.3]
79
+ end
80
+
74
81
  protected
75
82
  # @return [true,false] whether the server version is the same or
76
83
  # newer than the requested version
@@ -133,6 +133,22 @@ module Riak
133
133
  put(204, bucket_properties_path(bucket), body, {"Content-Type" => "application/json"})
134
134
  end
135
135
 
136
+ # Clears bucket properties
137
+ # @param [Bucket, String] bucket the bucket to clear properties
138
+ # on
139
+ # @return [true, false] whether the operation succeeded
140
+ # @note false will be returned if the operation is not supported
141
+ # on the connected node
142
+ def clear_bucket_props(bucket)
143
+ if http_props_clearable?
144
+ bucket = bucket.name if Bucket === bucket
145
+ delete(204, bucket_properties_path(bucket))
146
+ true
147
+ else
148
+ false
149
+ end
150
+ end
151
+
136
152
  # List keys in a bucket
137
153
  # @param [Bucket, String] bucket the bucket to fetch the keys
138
154
  # for
@@ -53,7 +53,7 @@ module Riak
53
53
  raise ArgumentError, t("stored_function_invalid") unless type == :link || value.has_key?(:bucket) && value.has_key?(:key)
54
54
  @language = "javascript"
55
55
  when String
56
- @language = "javascript"
56
+ @language = (value =~ /\s*fun\s*\(.*\)\s*->/) ? "erlang" : "javascript"
57
57
  when WalkSpec
58
58
  raise ArgumentError, t("walk_spec_invalid_unless_link") unless type == :link
59
59
  else
@@ -78,7 +78,7 @@ module Riak
78
78
  when Hash
79
79
  defaults.merge(function)
80
80
  when String
81
- if function =~ /\s*function/
81
+ if function =~ /\s*function\s*\(/ || function =~ /\s*fun\s*\(.*\)\s*->/
82
82
  defaults.merge("source" => function)
83
83
  else
84
84
  defaults.merge("name" => function)
@@ -1,3 +1,3 @@
1
1
  module Riak
2
- VERSION = "1.1.1"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -12,6 +12,7 @@ module Riak
12
12
  # Riak::WalkSpec.new({:bucket => 'tracks', :result => true})
13
13
  class WalkSpec
14
14
  include Util::Translation
15
+ extend Util::Translation
15
16
  include Util::Escape
16
17
 
17
18
  # @return [String] The bucket followed links should be restricted to. "_" represents all buckets.
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
12
12
  gem.authors = ["Sean Cribbs"]
13
13
 
14
14
  # Deps
15
- gem.add_development_dependency "rspec", "~>2.10.0"
15
+ gem.add_development_dependency "rspec", "~>2.13.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"
@@ -37,6 +37,21 @@ describe "HTTP" do
37
37
  end
38
38
  end
39
39
 
40
+ context "clearing bucket properties" do
41
+ it "should return false when unsupported", :version => "< 1.3.0" do
42
+ @backend.clear_bucket_props('foo').should be_false
43
+ end
44
+
45
+ it "should reset a previously set property to the default", :version => ">= 1.3.0" do
46
+ bucket = @client['bucketpropscleartest']
47
+ original_n = @backend.get_bucket_props(bucket)['n_val']
48
+ @backend.set_bucket_props(bucket, {'n_val' => 2})
49
+ @backend.get_bucket_props(bucket)['n_val'].should == 2
50
+ @backend.clear_bucket_props(bucket)
51
+ @backend.get_bucket_props(bucket)['n_val'].should == original_n
52
+ end
53
+ end
54
+
40
55
  context "using Luwak", :version => "< 1.1.0" do
41
56
  let(:file) { File.open(__FILE__) }
42
57
  let(:key) { "spec.rb" }
@@ -30,6 +30,20 @@ describe "Protocol Buffers" do
30
30
  results['docs'].should include({"id" => "munchausen-605"})
31
31
  end
32
32
  end
33
+
34
+ if "".respond_to?(:encoding) # Ruby 1.9 and later only
35
+ describe "searching fulltext indexes (1.2 and later)", :version => '>= 1.2.0' do
36
+ include_context "search corpus setup"
37
+
38
+ it 'should return documents with UTF-8 fields (GH #75)' do
39
+ utf8 = Encoding.find('UTF-8')
40
+ results = @backend.search 'search_test', 'fearless elephant rushed'
41
+ results['docs'].each do |d|
42
+ d.each {|(k,v)| k.encoding.should == utf8; v.encoding.should == utf8 }
43
+ end
44
+ end
45
+ end
46
+ end
33
47
  end
34
48
  end
35
49
  end
@@ -86,6 +86,14 @@ describe Riak::Bucket do
86
86
  end
87
87
  end
88
88
 
89
+ describe "clearing the bucket properties" do
90
+ it "should make the request and delete the internal properties cache" do
91
+ @client.should_receive(:clear_bucket_props).with(@bucket).and_return(true)
92
+ @bucket.clear_props.should be_true
93
+ @bucket.instance_variable_get(:@props).should be_nil
94
+ end
95
+ end
96
+
89
97
  describe "fetching an object" do
90
98
  it "should fetch the object via the backend" do
91
99
  @backend.should_receive(:fetch_object).with(@bucket, "db", {}).and_return(nil)
@@ -24,6 +24,7 @@ describe Riak::Client::FeatureDetection do
24
24
  it { should_not be_quorum_controls }
25
25
  it { should_not be_tombstone_vclocks }
26
26
  it { should_not be_pb_head }
27
+ it { should_not be_http_props_clearable }
27
28
  end
28
29
 
29
30
  context "when the Riak version is 1.0.x" do
@@ -35,6 +36,7 @@ describe Riak::Client::FeatureDetection do
35
36
  it { should be_quorum_controls }
36
37
  it { should be_tombstone_vclocks }
37
38
  it { should be_pb_head }
39
+ it { should_not be_http_props_clearable }
38
40
  end
39
41
 
40
42
  context "when the Riak version is 1.1.x" do
@@ -46,10 +48,11 @@ describe Riak::Client::FeatureDetection do
46
48
  it { should be_quorum_controls }
47
49
  it { should be_tombstone_vclocks }
48
50
  it { should be_pb_head }
51
+ it { should_not be_http_props_clearable }
49
52
  end
50
53
 
51
54
  context "when the Riak version is 1.2.x" do
52
- before { subject.stub!(:get_server_version).and_return("1.2.0") }
55
+ before { subject.stub!(:get_server_version).and_return("1.2.1") }
53
56
  it { should be_mapred_phaseless }
54
57
  it { should be_pb_indexes }
55
58
  it { should be_pb_search }
@@ -57,5 +60,18 @@ describe Riak::Client::FeatureDetection do
57
60
  it { should be_quorum_controls }
58
61
  it { should be_tombstone_vclocks }
59
62
  it { should be_pb_head }
63
+ it { should_not be_http_props_clearable }
64
+ end
65
+
66
+ context "when the Riak version is 1.3.x" do
67
+ before { subject.stub!(:get_server_version).and_return("1.3.0") }
68
+ it { should be_mapred_phaseless }
69
+ it { should be_pb_indexes }
70
+ it { should be_pb_search }
71
+ it { should be_pb_conditionals }
72
+ it { should be_quorum_controls }
73
+ it { should be_tombstone_vclocks }
74
+ it { should be_pb_head }
75
+ it { should be_http_props_clearable }
60
76
  end
61
77
  end
@@ -2,13 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe Riak::MapReduce::Phase do
4
4
  before :each do
5
- @fun = "function(v,_,_){ return v['values'][0]['data']; }"
5
+ @js_fun = "function(v,_,_){ return v['values'][0]['data']; }"
6
+ @erl_fun = "fun(Obj, _KeyData, _Arg) -> [{riak_object:key(Obj), riak_object:get_value(Obj)}] end."
6
7
  end
7
8
 
8
9
  it "should initialize with a type and a function" do
9
- phase = Riak::MapReduce::Phase.new(:type => :map, :function => @fun, :language => "javascript")
10
+ phase = Riak::MapReduce::Phase.new(:type => :map, :function => @js_fun, :language => "javascript")
10
11
  phase.type.should == :map
11
- phase.function.should == @fun
12
+ phase.function.should == @js_fun
12
13
  phase.language.should == "javascript"
13
14
  end
14
15
 
@@ -31,11 +32,16 @@ describe Riak::MapReduce::Phase do
31
32
  phase.language.should == "erlang"
32
33
  end
33
34
 
34
- it "should assume the language is javascript when the function is a string" do
35
- phase = Riak::MapReduce::Phase.new(:type => :map, :function => @fun)
35
+ it "should assume the language is javascript when the function is a string and starts with function" do
36
+ phase = Riak::MapReduce::Phase.new(:type => :map, :function => @js_fun)
36
37
  phase.language.should == "javascript"
37
38
  end
38
39
 
40
+ it "should assume the language is erlang when the function is a string and starts with anon fun" do
41
+ phase = Riak::MapReduce::Phase.new(:type => :map, :function => @erl_fun)
42
+ phase.language.should == "erlang"
43
+ end
44
+
39
45
  it "should assume the language is javascript when the function is a hash" do
40
46
  phase = Riak::MapReduce::Phase.new(:type => :map, :function => {:bucket => "jobs", :key => "awesome_map"})
41
47
  phase.language.should == "javascript"
@@ -101,6 +101,10 @@ describe Riak::WalkSpec do
101
101
  specs.should be_all {|s| s.kind_of?(Riak::WalkSpec) }
102
102
  specs.join("/").should == "_,next,_/foo,_,_/_,child,1"
103
103
  end
104
+
105
+ it "should raise an error when given invalid number of parameters" do
106
+ expect { Riak::WalkSpec.normalize("foo") }.to raise_error(ArgumentError)
107
+ end
104
108
  end
105
109
 
106
110
  describe "matching other objects with ===" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riak-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-10 00:00:00.000000000 Z
12
+ date: 2013-05-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.10.0
21
+ version: 2.13.0
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 2.10.0
29
+ version: 2.13.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: fakeweb
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -329,12 +329,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
329
329
  - - ! '>='
330
330
  - !ruby/object:Gem::Version
331
331
  version: '0'
332
+ segments:
333
+ - 0
334
+ hash: 20034304450029998
332
335
  required_rubygems_version: !ruby/object:Gem::Requirement
333
336
  none: false
334
337
  requirements:
335
338
  - - ! '>='
336
339
  - !ruby/object:Gem::Version
337
340
  version: '0'
341
+ segments:
342
+ - 0
343
+ hash: 20034304450029998
338
344
  requirements: []
339
345
  rubyforge_project:
340
346
  rubygems_version: 1.8.23