riak-client 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,10 +20,19 @@ module Riak
20
20
  # be preferred when the 'curb' library is available.
21
21
  # Conforms to the Riak::Client::HTTPBackend interface.
22
22
  class NetHTTPBackend < HTTPBackend
23
+ def self.configured?
24
+ begin
25
+ require 'net/http'
26
+ true
27
+ rescue LoadError, NameError
28
+ false
29
+ end
30
+ end
31
+
23
32
  private
24
33
  def perform(method, uri, headers, expect, data=nil) #:nodoc:
25
34
  Net::HTTP.start(uri.host, uri.port) do |http|
26
- request = Net::HTTP.const_get(method.to_s.camelize).new(uri.request_uri, headers)
35
+ request = Net::HTTP.const_get(method.to_s.capitalize).new(uri.request_uri, headers)
27
36
  case data
28
37
  when String
29
38
  request.body = data
@@ -40,7 +49,7 @@ module Riak
40
49
  result[:body] = response.body
41
50
  end
42
51
  else
43
- raise FailedRequest.new(method, expect, response.code, response.to_hash, response.body)
52
+ raise FailedRequest.new(method, expect, response.code.to_i, response.to_hash, response.body)
44
53
  end
45
54
  end
46
55
  end
@@ -0,0 +1,6 @@
1
+ require 'riak/core_ext/blank'
2
+ require 'riak/core_ext/extract_options'
3
+ require 'riak/core_ext/slice'
4
+ require 'riak/core_ext/stringify_keys'
5
+ require 'riak/core_ext/symbolize_keys'
6
+ require 'riak/core_ext/to_param'
@@ -0,0 +1,39 @@
1
+ unless Object.new.respond_to? :blank?
2
+ class Object
3
+ def blank?
4
+ false
5
+ end
6
+ end
7
+
8
+ class NilClass
9
+ def blank?
10
+ true
11
+ end
12
+ end
13
+
14
+ class Set
15
+ alias :blank? :empty?
16
+ end
17
+
18
+ class String
19
+ def blank?
20
+ not self =~ /[^\s]/
21
+ end
22
+ end
23
+
24
+ class Array
25
+ alias :blank? :empty?
26
+ end
27
+
28
+ class Hash
29
+ alias :blank? :empty?
30
+ end
31
+ end
32
+
33
+ unless Object.new.respond_to? :present?
34
+ class Object
35
+ def present?
36
+ not blank?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ unless Array.new.respond_to? :extract_options!
2
+ class Array
3
+ def extract_options!
4
+ last.is_a?(::Hash) ? pop : {}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ unless {}.respond_to? :slice
2
+ class Hash
3
+ def slice(*keys)
4
+ allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
5
+ hash = {}
6
+ allowed.each { |k| hash[k] = self[k] if has_key?(k) }
7
+ hash
8
+ end
9
+
10
+ def slice!(*keys)
11
+ keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
12
+ omit = slice(*self.keys - keys)
13
+ hash = slice(*keys)
14
+ replace(hash)
15
+ omit
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ unless {}.respond_to? :stringify_keys
2
+ class Hash
3
+ def stringify_keys
4
+ inject({}) do |hash, pair|
5
+ hash[pair[0].to_s] = pair[1]
6
+ hash
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ unless {}.respond_to? :symbolize_keys
2
+ class Hash
3
+ def symbolize_keys
4
+ inject({}) do |hash, pair|
5
+ hash[pair[0].to_sym] = pair[1]
6
+ hash
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ unless Object.new.respond_to? :to_query and Object.new.respond_to? :to_param
2
+ class Object
3
+ def to_param
4
+ to_s
5
+ end
6
+
7
+ def to_query(key)
8
+ require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
9
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
10
+ end
11
+ end
12
+
13
+ class Array
14
+ def to_param
15
+ map(&:to_param).join('/')
16
+ end
17
+
18
+ def to_query(key)
19
+ prefix = "#{key}[]"
20
+ collect { |value| value.to_query(prefix) }.join '&'
21
+ end
22
+ end
23
+
24
+ class Hash
25
+ def to_param
26
+ map do |key, value|
27
+ value.to_query(key)
28
+ end.sort * '&'
29
+ end
30
+ end
31
+ end
data/lib/riak/i18n.rb CHANGED
@@ -11,10 +11,6 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- if ActiveSupport::VERSION::STRING >= "3.0"
15
- require 'active_support/i18n'
16
- else
17
- require 'i18n' # support ActiveSupport < 3
18
- end
14
+ require 'i18n'
19
15
 
20
16
  I18n.load_path << File.expand_path("../locale/en.yml", __FILE__)
data/lib/riak/link.rb CHANGED
@@ -17,13 +17,18 @@ module Riak
17
17
  # Represents a link from one object to another in Riak
18
18
  class Link
19
19
  include Util::Translation
20
- # @return [String] the URL (relative or absolute) of the related resource
21
- attr_accessor :url
20
+ include Util::Escape
21
+
22
+ # @return [String] the relationship tag (or "rel") of the other resource to this one
23
+ attr_accessor :tag
24
+ alias_method :rel, :tag
25
+ alias_method :rel=, :tag=
26
+
27
+ # @return [String] the bucket of the related resource
28
+ attr_accessor :bucket
22
29
 
23
- # @return [String] the relationship ("rel") of the other resource to this one
24
- attr_accessor :rel
25
- alias :tag :rel
26
- alias :tag= :rel=
30
+ # @return [String] the key of the related resource
31
+ attr_accessor :key
27
32
 
28
33
  # @param [String] header_string the string value of the Link: HTTP header from a Riak response
29
34
  # @return [Array<Link>] an array of Riak::Link structs parsed from the header
@@ -33,24 +38,36 @@ module Riak
33
38
  end
34
39
  end
35
40
 
36
- def initialize(url, rel)
37
- @url, @rel = url, rel
41
+ # @overload initialize(url, tag)
42
+ # @param [String] url the url of the related resource
43
+ # @param [String] tag the tag for the related resource
44
+ # @overload initialize(bucket, key, tag)
45
+ # @param [String] bucket the bucket of the related resource
46
+ # @param [String] key the key of the related resource
47
+ # @param [String] tag the tag for the related resource
48
+ def initialize(*args)
49
+ raise ArgumentError unless (2..3).include?(args.size)
50
+ if args.size == 2
51
+ self.url, @tag = args
52
+ else
53
+ @bucket, @key, @tag = args
54
+ end
38
55
  end
39
56
 
40
- # @return [String] bucket_name, if the Link url is a known Riak link ("/riak/<bucket>/<key>")
41
- def bucket
42
- CGI.unescape($1) if url =~ %r{^/[^/]+/([^/]+)/?}
57
+ # @return [String] the URL (relative or absolute) of the related resource
58
+ def url
59
+ "/riak/#{escape(bucket)}" + (key.blank? ? "" : "/#{escape(key)}")
43
60
  end
44
-
45
- # @return [String] key, if the Link url is a known Riak link ("/riak/<bucket>/<key>")
46
- def key
47
- CGI.unescape($1) if url =~ %r{^/[^/]+/[^/]+/([^/]+)/?}
61
+
62
+ def url=(value)
63
+ @bucket = CGI.unescape($1) if value =~ %r{^/[^/]+/([^/]+)/?}
64
+ @key = CGI.unescape($1) if value =~ %r{^/[^/]+/[^/]+/([^/]+)/?}
48
65
  end
49
66
 
50
67
  def inspect; to_s; end
51
68
 
52
69
  def to_s
53
- %Q[<#{@url}>; riaktag="#{@rel}"]
70
+ %Q[<#{url}>; riaktag="#{tag}"]
54
71
  end
55
72
 
56
73
  def hash
@@ -62,12 +79,12 @@ module Riak
62
79
  end
63
80
 
64
81
  def ==(other)
65
- other.is_a?(Link) && url == other.url && rel == other.rel
82
+ other.is_a?(Link) && url == other.url && tag == other.tag
66
83
  end
67
84
 
68
85
  def to_walk_spec
69
- raise t("bucket_link_conversion") if @rel == "up" || key.nil?
70
- WalkSpec.new(:bucket => bucket, :tag => @rel)
86
+ raise t("bucket_link_conversion") if tag == "up" || key.nil?
87
+ WalkSpec.new(:bucket => bucket, :tag => tag)
71
88
  end
72
89
  end
73
90
  end
@@ -19,8 +19,8 @@ en:
19
19
  empty_map_reduce_query: "Specify one or more query phases to your MapReduce."
20
20
  failed_request: "Expected %{expected} from Riak but received %{code}. %{body}"
21
21
  hash_type: "invalid argument %{hash} is not a Hash"
22
+ http_configuration: "The %{backend} HTTP backend cannot be used. Please check its requirements."
22
23
  hostname_invalid: "host must be a valid hostname"
23
- install_curb: "curb library not found! Please `gem install curb` for better performance."
24
24
  invalid_client_id: "Invalid client ID, must be a string or between 0 and %{max_id}"
25
25
  invalid_function_value: "invalid value for function: %{value}"
26
26
  invalid_phase_type: "type must be :map, :reduce, or :link"
@@ -137,10 +137,10 @@ module Riak
137
137
 
138
138
  # Convert the job to JSON for submission over the HTTP interface.
139
139
  # @return [String] the JSON representation
140
- def to_json(options={})
141
- hash = {"inputs" => inputs.as_json, "query" => query.map(&:as_json)}
140
+ def to_json(*a)
141
+ hash = {"inputs" => inputs, "query" => query.map(&:as_json)}
142
142
  hash['timeout'] = @timeout.to_i if @timeout
143
- ActiveSupport::JSON.encode(hash, options)
143
+ hash.to_json(*a)
144
144
  end
145
145
 
146
146
  # Executes this map-reduce job.
@@ -148,9 +148,10 @@ module Riak
148
148
  def run
149
149
  raise MapReduceError.new(t("empty_map_reduce_query")) if @query.empty?
150
150
  response = @client.http.post(200, @client.mapred, to_json, {"Content-Type" => "application/json", "Accept" => "application/json"})
151
- if response.try(:[], :headers).try(:[],'content-type').include?("application/json")
152
- ActiveSupport::JSON.decode(response[:body])
153
- else
151
+ begin
152
+ raise unless response[:headers]['content-type'].include?('application/json')
153
+ JSON.parse(response[:body])
154
+ rescue
154
155
  response
155
156
  end
156
157
  rescue FailedRequest => fr
@@ -220,8 +221,8 @@ module Riak
220
221
 
221
222
  # Converts the phase to JSON for use while invoking a job.
222
223
  # @return [String] a JSON representation of the phase
223
- def to_json(options=nil)
224
- ActiveSupport::JSON.encode(as_json, options)
224
+ def to_json(*a)
225
+ as_json.to_json(*a)
225
226
  end
226
227
 
227
228
  # Converts the phase to its JSON-compatible representation for job invocation.
data/lib/riak/robject.rb CHANGED
@@ -33,7 +33,6 @@ module Riak
33
33
 
34
34
  # @return [String] the Riak vector clock for the object
35
35
  attr_accessor :vclock
36
- alias_attribute :vector_clock, :vclock
37
36
 
38
37
  # @return [Set<Link>] a Set of {Riak::Link} objects for relationships between this object and other resources
39
38
  attr_accessor :links
@@ -88,7 +87,7 @@ module Riak
88
87
  end
89
88
  h
90
89
  end
91
- @conflict = response[:code].try(:to_i) == 300 && content_type =~ /multipart\/mixed/
90
+ @conflict = (response[:code].to_i == 300 && content_type =~ /multipart\/mixed/) rescue false
92
91
  @siblings = nil
93
92
  self.raw_data = response[:body] if response[:body].present?
94
93
  self
@@ -250,7 +249,7 @@ module Riak
250
249
  return payload if IO === payload
251
250
  case @content_type
252
251
  when /json/
253
- ActiveSupport::JSON.encode(payload)
252
+ payload.to_json
254
253
  when /yaml/
255
254
  YAML.dump(payload)
256
255
  when "application/x-ruby-marshal"
@@ -270,7 +269,7 @@ module Riak
270
269
  def deserialize(body)
271
270
  case @content_type
272
271
  when /json/
273
- ActiveSupport::JSON.decode(body)
272
+ JSON.parse(body)
274
273
  when /yaml/
275
274
  YAML.load(body)
276
275
  when "application/x-ruby-marshal"
@@ -282,7 +281,12 @@ module Riak
282
281
 
283
282
  # @return [String] A representation suitable for IRB and debugging output
284
283
  def inspect
285
- "#<#{self.class.name} #{url} [#{@content_type}]:#{@data.inspect}>"
284
+ body = if @data || content_type =~ /json|yaml|marshal/
285
+ data.inspect
286
+ else
287
+ @raw_data && "(#{@raw_data.size} bytes)"
288
+ end
289
+ "#<#{self.class.name} #{url} [#{@content_type}]:#{body}>"
286
290
  end
287
291
 
288
292
  # Walks links from this object to other objects in Riak.
@@ -303,7 +307,7 @@ module Riak
303
307
  # to it
304
308
  # @param [String] tag the tag to apply to the link
305
309
  def to_link(tag)
306
- Link.new(@bucket.client.http.path(@bucket.client.prefix, escape(@bucket.name), escape(@key)).path, tag)
310
+ Link.new(@bucket.name, @key, tag)
307
311
  end
308
312
 
309
313
  # Generates a URL representing the object according to the client, bucket and key.
@@ -315,6 +319,9 @@ module Riak
315
319
  @bucket.client.http.path(*segments).to_s
316
320
  end
317
321
 
322
+ alias :vector_clock :vclock
323
+ alias :vector_clock= :vclock=
324
+
318
325
  protected
319
326
  def load_map_reduce_value(hash)
320
327
  metadata = hash['metadata']
data/lib/riak/search.rb CHANGED
@@ -52,7 +52,7 @@ module Riak
52
52
  path = [solr, index, "select", {"q" => query, "wt" => "json"}.merge(options.stringify_keys), {}].compact
53
53
  response = http.get(200, *path)
54
54
  if response[:headers]['content-type'].include?("application/json")
55
- ActiveSupport::JSON.decode(response[:body])
55
+ JSON.parse(response[:body])
56
56
  else
57
57
  response[:body]
58
58
  end
@@ -98,7 +98,12 @@ module Riak
98
98
  # @raise [ArgumentError] if any document specs don't include 'id' or 'query' keys
99
99
  def remove(*args)
100
100
  index = args.shift if String === args.first
101
- raise ArgumentError.new(t("search_remove_requires_id_or_query")) unless args.all? {|s| s.stringify_keys.key?("id") || s.stringify_keys.key?("query") }
101
+ raise ArgumentError.new(t("search_remove_requires_id_or_query")) unless args.all? { |s|
102
+ s.include? :id or
103
+ s.include? 'id' or
104
+ s.include? :query or
105
+ s.include? 'query'
106
+ }
102
107
  xml = Builder::XmlMarkup.new
103
108
  xml.delete do
104
109
  args.each do |spec|
@@ -88,6 +88,7 @@ module Riak
88
88
  @mutex.synchronize do
89
89
  @cin, @cout, @cerr, @cpid = Open3.popen3("#{@riak_script} console")
90
90
  @cin.puts
91
+ @cin.flush
91
92
  wait_for_erlang_prompt
92
93
  @started = true
93
94
  end
@@ -100,6 +101,7 @@ module Riak
100
101
  @mutex.synchronize do
101
102
  begin
102
103
  @cin.puts "init:stop()."
104
+ @cin.flush
103
105
  rescue Errno::EPIPE
104
106
  ensure
105
107
  register_stop
@@ -122,9 +124,11 @@ module Riak
122
124
  begin
123
125
  if @app_config[:riak_kv][:storage_backend] == :riak_kv_test_backend
124
126
  @cin.puts "riak_kv_test_backend:reset()."
127
+ @cin.flush
125
128
  wait_for_erlang_prompt
126
129
  else
127
130
  @cin.puts "init:restart()."
131
+ @cin.flush
128
132
  wait_for_erlang_prompt
129
133
  wait_for_startup
130
134
  end
@@ -224,7 +228,7 @@ module Riak
224
228
  def register_stop
225
229
  %w{@cin @cout @cerr}.each {|io| if instance_variable_get(io); instance_variable_get(io).close; instance_variable_set(io, nil) end }
226
230
  _cpid = @cpid; @cpid = nil
227
- at_exit { _cpid.join if _cpid.alive? }
231
+ at_exit { _cpid.join if _cpid && _cpid.alive? }
228
232
  @started = false
229
233
  end
230
234
  end
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{riak-client}
5
+ s.version = "0.8.3"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Sean Cribbs"]
9
+ s.date = %q{2010-12-13}
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
+ 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"]
13
+ s.homepage = %q{http://seancribbs.github.com/ripple}
14
+ s.require_paths = ["lib"]
15
+ s.rubygems_version = %q{1.3.7}
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"]
18
+
19
+ if s.respond_to? :specification_version then
20
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
21
+ s.specification_version = 3
22
+
23
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
24
+ s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
25
+ s.add_development_dependency(%q<fakeweb>, [">= 1.2"])
26
+ s.add_development_dependency(%q<rack>, [">= 1.0"])
27
+ s.add_development_dependency(%q<curb>, [">= 0.6"])
28
+ s.add_development_dependency(%q<excon>, ["~> 0.3.4"])
29
+ s.add_runtime_dependency(%q<i18n>, [">= 0.4.0"])
30
+ s.add_runtime_dependency(%q<builder>, ["~> 2.1.2"])
31
+ else
32
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
33
+ s.add_dependency(%q<fakeweb>, [">= 1.2"])
34
+ s.add_dependency(%q<rack>, [">= 1.0"])
35
+ s.add_dependency(%q<curb>, [">= 0.6"])
36
+ s.add_dependency(%q<excon>, ["~> 0.3.4"])
37
+ s.add_dependency(%q<i18n>, [">= 0.4.0"])
38
+ s.add_dependency(%q<builder>, ["~> 2.1.2"])
39
+ end
40
+ else
41
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
42
+ s.add_dependency(%q<fakeweb>, [">= 1.2"])
43
+ s.add_dependency(%q<rack>, [">= 1.0"])
44
+ s.add_dependency(%q<curb>, [">= 0.6"])
45
+ s.add_dependency(%q<excon>, ["~> 0.3.4"])
46
+ s.add_dependency(%q<i18n>, [">= 0.4.0"])
47
+ s.add_dependency(%q<builder>, ["~> 2.1.2"])
48
+ end
49
+ end