riak-client 0.8.0.beta2 → 0.8.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.
@@ -44,6 +44,7 @@ module Riak
44
44
  autoload :InvalidResponse, "riak/invalid_response"
45
45
  autoload :MapReduceError, "riak/map_reduce_error"
46
46
 
47
+ # Utility classes and mixins
47
48
  module Util
48
49
  autoload :Escape, "riak/util/escape"
49
50
  autoload :Headers, "riak/util/headers"
@@ -177,7 +177,8 @@ module Riak
177
177
  def n_value
178
178
  props['n_val']
179
179
  end
180
-
180
+ alias :n_val :n_value
181
+
181
182
  # Set the N value (number of replicas). *NOTE* This will result in a PUT request to Riak.
182
183
  # Setting this value after the bucket has objects stored in it may have unpredictable results.
183
184
  # @param [Fixnum] value the number of replicas the bucket should keep of each object
@@ -185,7 +186,8 @@ module Riak
185
186
  self.props = {'n_val' => value}
186
187
  value
187
188
  end
188
-
189
+ alias :n_val= :n_value=
190
+
189
191
  [:r,:w,:dw,:rw].each do |q|
190
192
  class_eval <<-CODE
191
193
  def #{q}
@@ -12,10 +12,14 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  require 'riak'
15
+
15
16
  module Riak
17
+ # An ActiveSupport::Cache::Store implementation that uses Riak.
18
+ # Compatible only with ActiveSupport version 3 or greater.
16
19
  class CacheStore < ActiveSupport::Cache::Store
17
20
  attr_accessor :client
18
21
 
22
+ # Creates a Riak-backed cache store.
19
23
  def initialize(options = {})
20
24
  super
21
25
  @bucket_name = options.delete(:bucket) || '_cache'
@@ -29,7 +29,7 @@ module Riak
29
29
  private
30
30
  def perform(method, uri, headers, expect, data=nil)
31
31
  # Setup
32
- curl.headers = headers
32
+ curl.headers = create_request_headers(headers)
33
33
  curl.url = uri.to_s
34
34
  response_headers.initialize_http_header(nil)
35
35
  if block_given?
@@ -46,8 +46,15 @@ module Riak
46
46
  end
47
47
  # Perform
48
48
  case method
49
- when :put, :post
50
- curl.send("http_#{method}", data)
49
+ when :post
50
+ data = data.read if data.respond_to?(:read)
51
+ curl.http_post(data)
52
+ when :put
53
+ # Hacks around limitations in curb's PUT semantics
54
+ _headers, curl.headers = curl.headers, {}
55
+ curl.put_data = data
56
+ curl.headers = create_request_headers(curl.headers) + _headers
57
+ curl.http("PUT")
51
58
  else
52
59
  curl.send("http_#{method}")
53
60
  end
@@ -77,6 +84,16 @@ module Riak
77
84
  def response_headers
78
85
  Thread.current[:response_headers] ||= Riak::Util::Headers.new
79
86
  end
87
+
88
+ def create_request_headers(hash)
89
+ h = Riak::Util::Headers.new
90
+ hash.each {|k,v| h.add_field(k,v) }
91
+ [].tap do |arr|
92
+ h.each_capitalized do |k,v|
93
+ arr << "#{k}: #{v}"
94
+ end
95
+ end
96
+ end
80
97
  end
81
98
  end
82
99
  end
@@ -15,6 +15,7 @@ require 'riak'
15
15
 
16
16
  module Riak
17
17
  class Client
18
+ # The parent class for all backends that connect to Riak via HTTP.
18
19
  class HTTPBackend
19
20
  include Util::Translation
20
21
  # The Riak::Client that uses this backend
@@ -161,7 +161,7 @@ module Riak
161
161
  end
162
162
 
163
163
  # Represents an individual phase in a map-reduce pipeline. Generally you'll want to call
164
- # methods of {MapReduce} instead of using this directly.
164
+ # methods of MapReduce instead of using this directly.
165
165
  class Phase
166
166
  include Util::Translation
167
167
  # @return [Symbol] the type of phase - :map, :reduce, or :link
@@ -15,8 +15,8 @@ require 'riak'
15
15
  require 'set'
16
16
 
17
17
  module Riak
18
- # Parent class of all object types supported by ripple. {Riak::RObject} represents
19
- # the data and metadata stored in a bucket/key pair in the Riak database.
18
+ # Represents the data and metadata stored in a bucket/key pair in
19
+ # the Riak database, the base unit of data manipulation.
20
20
  class RObject
21
21
  include Util
22
22
  include Util::Translation
@@ -52,10 +52,8 @@ module Riak
52
52
 
53
53
  # Loads a list of RObjects that were emitted from a MapReduce
54
54
  # query.
55
- # @param [Client] client A Riak::Client with which the results will be
56
- # associated
57
- # @param [Array<Hash>] response A list of results a MapReduce job. Each
58
- # entry should contain these keys: bucket, key, vclock, values
55
+ # @param [Client] client A Riak::Client with which the results will be associated
56
+ # @param [Array<Hash>] response A list of results a MapReduce job. Each entry should contain these keys: bucket, key, vclock, values
59
57
  # @return [Array<RObject>] An array of RObject instances
60
58
  def self.load_from_mapreduce(client, response)
61
59
  response.map do |item|
@@ -66,6 +64,7 @@ module Riak
66
64
  # Create a new object manually
67
65
  # @param [Bucket] bucket the bucket in which the object exists
68
66
  # @param [String] key the key at which the object resides. If nil, a key will be assigned when the object is saved.
67
+ # @yield self the new RObject
69
68
  # @see Bucket#get
70
69
  def initialize(bucket, key=nil)
71
70
  @bucket, @key = bucket, key
@@ -205,7 +204,9 @@ module Riak
205
204
  # Automatically serialized formats:
206
205
  # * JSON (application/json)
207
206
  # * YAML (text/yaml)
208
- # * Marshal (application/octet-stream if meta['ruby-serialization'] == "Marshal")
207
+ # * Marshal (application/x-ruby-marshal)
208
+ # When given an IO-like object (e.g. File), no serialization will
209
+ # be done.
209
210
  # @param [Object] payload the data to serialize
210
211
  def serialize(payload)
211
212
  return payload if IO === payload
@@ -226,7 +227,7 @@ module Riak
226
227
  # Automatically deserialized formats:
227
228
  # * JSON (application/json)
228
229
  # * YAML (text/yaml)
229
- # * Marshal (application/octet-stream if meta['ruby-serialization'] == "Marshal")
230
+ # * Marshal (application/x-ruby-marshal)
230
231
  # @param [String] body the serialized response body
231
232
  def deserialize(body)
232
233
  case @content_type
@@ -247,6 +248,7 @@ module Riak
247
248
  end
248
249
 
249
250
  # Walks links from this object to other objects in Riak.
251
+ # @param [Array<Hash,WalkSpec>] link specifications for the query
250
252
  def walk(*params)
251
253
  specs = WalkSpec.normalize(*params)
252
254
  response = @bucket.client.http.get(200, @bucket.client.prefix, escape(@bucket.name), escape(@key), specs.join("/"))
@@ -259,7 +261,9 @@ module Riak
259
261
  end
260
262
  end
261
263
 
262
- # Converts the object to a link suitable for linking other objects to it
264
+ # Converts the object to a link suitable for linking other objects
265
+ # to it
266
+ # @param [String] tag the tag to apply to the link
263
267
  def to_link(tag)
264
268
  Link.new(@bucket.client.http.path(@bucket.client.prefix, escape(@bucket.name), escape(@key)).path, tag)
265
269
  end
@@ -1,5 +1,21 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require 'riak'
15
+
1
16
  module Riak
2
17
  module Util
18
+ # Methods for escaping URL segments.
3
19
  module Escape
4
20
  # CGI-escapes bucket or key names that may contain slashes for use in URLs.
5
21
  # @param [String] bucket_or_key the bucket or key name
@@ -14,6 +14,7 @@
14
14
  require 'riak'
15
15
 
16
16
  # Splits headers into < 8KB chunks
17
+ # @private
17
18
  module Net::HTTPHeader
18
19
  def each_capitalized
19
20
  # 1.9 check
@@ -35,7 +36,8 @@ end
35
36
 
36
37
  module Riak
37
38
  module Util
38
- # Represents headers from an HTTP response
39
+ # Represents headers from an HTTP request or response.
40
+ # Used internally by HTTP backends for processing headers.
39
41
  class Headers
40
42
  include Net::HTTPHeader
41
43
 
@@ -15,11 +15,14 @@ require 'riak'
15
15
 
16
16
  module Riak
17
17
  module Util
18
+ # Methods for doing i18n string lookup
18
19
  module Translation
20
+ # The scope of i18n messages
19
21
  def i18n_scope
20
22
  :riak
21
23
  end
22
24
 
25
+ # Provides the translation for a given internationalized message
23
26
  def t(message, options={})
24
27
  I18n.t("#{i18n_scope}.#{message}", options)
25
28
  end
@@ -14,7 +14,6 @@
14
14
  require 'riak'
15
15
 
16
16
  module Riak
17
-
18
17
  # The specification of how to follow links from one object to another in Riak,
19
18
  # when using the link-walker resource.
20
19
  # Example link-walking operation:
@@ -20,7 +20,7 @@ rescue LoadError
20
20
  else
21
21
  $server = MockServer.new
22
22
  at_exit { $server.stop }
23
-
23
+
24
24
  describe Riak::Client::CurbBackend do
25
25
  def setup_http_mock(method, uri, options={})
26
26
  method = method.to_s.upcase
@@ -46,8 +46,32 @@ else
46
46
 
47
47
  it_should_behave_like "HTTP backend"
48
48
 
49
+ it "should split long headers into 8KB chunks" do
50
+ setup_http_mock(:put, @backend.path("/riak/","foo").to_s, :body => "ok")
51
+ lambda do
52
+ @backend.put(200, "/riak/", "foo", "body",{"Long-Header" => (["12345678"*10]*100).join(", ") })
53
+ headers = @backend.send(:curl).headers
54
+ headers.should be_kind_of(Array)
55
+ headers.select {|h| h =~ /^Long-Header:/ }.should have(2).items
56
+ headers.select {|h| h =~ /^Long-Header:/ }.should be_all {|h| h.size < 8192 }
57
+ end.should_not raise_error
58
+ end
59
+
60
+ it "should support IO objects as the request body" do
61
+ file = File.open(File.expand_path("../../fixtures/cat.jpg", __FILE__))
62
+ lambda do
63
+ setup_http_mock(:put, @backend.path("/riak/","foo").to_s, :body => "ok")
64
+ @backend.put(200, "/riak/", "foo", file,{})
65
+ end.should_not raise_error
66
+ lambda do
67
+ setup_http_mock(:post, @backend.path("/riak/","foo").to_s, :body => "ok")
68
+ @backend.post(200, "/riak/", "foo", file, {})
69
+ end.should_not raise_error
70
+ end
71
+
49
72
  after :each do
50
73
  $server.detach
74
+ Thread.current[:curl_easy_handle] = nil
51
75
  end
52
76
  end
53
77
  end
@@ -1,3 +1,17 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
1
15
  require File.expand_path("../../spec_helper", __FILE__)
2
16
 
3
17
  describe Riak::Util::Escape do
@@ -1,3 +1,17 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
1
15
  def mock_response(overrides={})
2
16
  {:headers => {"content-type" => ["application/json"]}, :body => '{}'}.merge(overrides)
3
- end
17
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riak-client
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 0
7
7
  - 8
8
8
  - 0
9
- - beta2
10
- version: 0.8.0.beta2
9
+ version: 0.8.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Sean Cribbs
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-08-29 00:00:00 -04:00
17
+ date: 2010-08-31 00:00:00 -04:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -181,13 +180,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
181
180
  required_rubygems_version: !ruby/object:Gem::Requirement
182
181
  none: false
183
182
  requirements:
184
- - - ">"
183
+ - - ">="
185
184
  - !ruby/object:Gem::Version
186
185
  segments:
187
- - 1
188
- - 3
189
- - 1
190
- version: 1.3.1
186
+ - 0
187
+ version: "0"
191
188
  requirements:
192
189
  - `gem install curb` for better HTTP performance
193
190
  rubyforge_project: