Created
July 6, 2010 09:10
-
-
Save tisba/465200 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/riak-client/lib/riak/client.rb b/riak-client/lib/riak/client.rb | |
index 127c2c8..be94f75 100644 | |
--- a/riak-client/lib/riak/client.rb | |
+++ b/riak-client/lib/riak/client.rb | |
@@ -35,6 +35,9 @@ module Riak | |
# @return [Fixnum] The port of the Riak HTTP endpoint | |
attr_reader :port | |
+ # @return [Array] of Riak HTTP endpoint hashes each consisting of :host and :port | |
+ attr_accessor :backends | |
+ | |
# @return [String] The internal client ID used by Riak to route responses | |
attr_reader :client_id | |
@@ -60,6 +63,24 @@ module Riak | |
self.prefix = options[:prefix] || "/riak/" | |
self.mapred = options[:mapred] || "/mapred" | |
raise ArgumentError, t("missing_host_and_port") unless @host && @port | |
+ | |
+ self.backends = [{:host => self.host, :port => self.port}] | |
+ end | |
+ | |
+ # Add a backend to the pool | |
+ # @param [String] the host (IP or hostname) of the riak node to be added | |
+ # @param [Fixnum] the port of the riak node to be added | |
+ def add_backend(host, port) | |
+ self.backends << {:host => host, :port => port} | |
+ end | |
+ | |
+ # Switches through the backends by settinh the next one and appending the current to the end of the pool | |
+ # @return [Hash] the new backend (may be the same, if self.backends only contains one element) | |
+ def next_backend | |
+ self.backends << self.backends.shift | |
+ self.host = self.backends[0][:host] | |
+ self.port = self.backends[0][:port] | |
+ self.backends[0] | |
end | |
# Set the client ID for this client. Must be a string or Fixnum value 0 =< value < MAX_CLIENT_ID. | |
diff --git a/riak-client/lib/riak/client/http_backend.rb b/riak-client/lib/riak/client/http_backend.rb | |
index 072c4f7..ff63f3f 100644 | |
--- a/riak-client/lib/riak/client/http_backend.rb | |
+++ b/riak-client/lib/riak/client/http_backend.rb | |
@@ -68,7 +68,9 @@ module Riak | |
def get(expect, *resource, &block) | |
headers = default_headers.merge(resource.extract_options!) | |
verify_path!(resource) | |
- perform(:get, path(*resource), headers, expect, &block) | |
+ retry_and_switch_backend_if_needed do | |
+ perform(:get, path(*resource), headers, expect, &block) | |
+ end | |
end | |
# Performs a PUT request to the specified resource on the Riak server. | |
@@ -89,7 +91,9 @@ module Riak | |
def put(expect, *resource, &block) | |
headers = default_headers.merge(resource.extract_options!) | |
uri, data = verify_path_and_body!(resource) | |
- perform(:put, path(*uri), headers, expect, data, &block) | |
+ retry_and_switch_backend_if_needed do | |
+ perform(:put, path(*uri), headers, expect, data, &block) | |
+ end | |
end | |
# Performs a POST request to the specified resource on the Riak server. | |
@@ -110,7 +114,9 @@ module Riak | |
def post(expect, *resource, &block) | |
headers = default_headers.merge(resource.extract_options!) | |
uri, data = verify_path_and_body!(resource) | |
- perform(:post, path(*uri), headers, expect, data, &block) | |
+ retry_and_switch_backend_if_needed do | |
+ perform(:post, path(*uri), headers, expect, data, &block) | |
+ end | |
end | |
# Performs a DELETE request to the specified resource on the Riak server. | |
@@ -130,7 +136,9 @@ module Riak | |
def delete(expect, *resource, &block) | |
headers = default_headers.merge(resource.extract_options!) | |
verify_path!(resource) | |
- perform(:delete, path(*resource), headers, expect, &block) | |
+ retry_and_switch_backend_if_needed do | |
+ perform(:delete, path(*resource), headers, expect, &block) | |
+ end | |
end | |
# @return [URI] The calculated root URI for the Riak HTTP endpoint | |
@@ -170,7 +178,7 @@ module Riak | |
resource = Array(resource).flatten | |
raise ArgumentError, t("resource_path_short") unless resource.length > 1 || resource.include?(@client.mapred) | |
end | |
- | |
+ | |
# Checks the expected response codes against the actual response code. Use internally when | |
# implementing {#perform}. | |
# @param [String, Fixnum, Array<String,Fixnum>] expected the expected response code(s) | |
@@ -189,7 +197,7 @@ module Riak | |
def return_body?(method, code, has_block) | |
method != :head && !valid_response?([204,205,304], code) && !has_block | |
end | |
- | |
+ | |
# Executes requests according to the underlying HTTP client library semantics. | |
# @abstract Subclasses must implement this internal method to perform HTTP requests | |
# according to the API of their HTTP libraries. | |
@@ -204,6 +212,23 @@ module Riak | |
def perform(method, uri, headers, expect, body=nil) | |
raise NotImplementedError | |
end | |
+ | |
+ private | |
+ | |
+ # Meant to be used internally for the get, put, post and delete methods | |
+ # to keep them DRY and catch errors from the (actual) HTTP backend | |
+ # implementation, switch the backend and retry again. FailedRequest | |
+ # Exceptions are raised again | |
+ def retry_and_switch_backend_if_needed | |
+ begin | |
+ yield | |
+ rescue Exception => e | |
+ raise e if e.class == FailedRequest | |
+ warn t("backend_not_working", :uri => root_uri.to_s, :exception => e.to_s) | |
+ client.next_backend | |
+ retry | |
+ end | |
+ end | |
end | |
end | |
end | |
diff --git a/riak-client/lib/riak/locale/en.yml b/riak-client/lib/riak/locale/en.yml | |
index 9a217fb..4c95291 100644 | |
--- a/riak-client/lib/riak/locale/en.yml | |
+++ b/riak-client/lib/riak/locale/en.yml | |
@@ -35,3 +35,4 @@ en: | |
too_few_arguments: "too few arguments: %{params}" | |
walk_spec_invalid_unless_link: "WalkSpec is only valid for a function when the type is :link" | |
wrong_argument_count_walk_spec: "wrong number of arguments (one Hash or bucket,tag,keep required)" | |
+ backend_not_working: "backend %{uri} is not working properly: %{exception}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment