riak-client 0.8.0.beta2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: