lib/moped/cluster.rb in moped-1.2.6 vs lib/moped/cluster.rb in moped-1.2.7

- old
+ new

@@ -2,12 +2,13 @@ # The cluster represents a cluster of MongoDB server nodes, either a single # node, a replica set, or a mongos server. class Cluster + # @attribute [r] options The cluster options. # @attribute [r] seeds The seeds the cluster was initialized with. - attr_reader :seeds + attr_reader :options, :seeds # Get the authentication details for the cluster. # # @example Get the authentication details. # cluster.auth @@ -28,10 +29,61 @@ # @since 1.2.0 def disconnect nodes.each { |node| node.disconnect } and true end + # Get the interval at which a node should be flagged as down before + # retrying. + # + # @example Get the down interval, in seconds. + # cluster.down_interval + # + # @return [ Integer ] The down interval. + # + # @since 1.2.7 + def down_interval + options[:down_interval] + end + + # Get the number of times an operation should be retried before raising an + # error. + # + # @example Get the maximum retries. + # cluster.max_retries + # + # @return [ Integer ] The max retries. + # + # @since 1.2.7 + def max_retries + options[:max_retries] + end + + # Get the interval in which the node list should be refreshed. + # + # @example Get the refresh interval, in seconds. + # cluster.refresh_interval + # + # @return [ Integer ] The refresh interval. + # + # @since 1.2.7 + def refresh_interval + options[:refresh_interval] + end + + # Get the operation retry interval - the time to wait before retrying a + # single operation. + # + # @example Get the retry interval, in seconds. + # cluster.retry_interval + # + # @return [ Integer ] The retry interval. + # + # @since 1.2.7 + def retry_interval + options[:retry_interval] + end + # Initialize the new cluster. # # @example Initialize the cluster. # Cluster.new([ "localhost:27017" ], down_interval: 20) # @@ -44,11 +96,13 @@ # # @since 1.0.0 def initialize(hosts, options) @options = { down_interval: 30, - refresh_interval: 300 + max_retries: 30, + refresh_interval: 300, + retry_interval: 1 }.merge(options) @seeds = hosts @nodes = hosts.map { |host| Node.new(host) } end @@ -63,12 +117,12 @@ # @return [ Array<Node> ] the list of available nodes. # # @since 1.0.0 def nodes current_time = Time.new - down_boundary = current_time - @options[:down_interval] - refresh_boundary = current_time - @options[:refresh_interval] + down_boundary = current_time - down_interval + refresh_boundary = current_time - refresh_interval # Find the nodes that were down but are ready to be refreshed, or those # with stale connection information. needs_refresh, available = @nodes.partition do |node| (node.down? && node.down_at < down_boundary) || node.needs_refresh?(refresh_boundary) @@ -133,19 +187,18 @@ # @example Yield the primary to the block. # cluster.with_primary do |node| # # ... # end # - # @param [ true, false ] retry_on_failure Whether to retry if an error was - # raised. + # @param [ Integer ] retries The number of times to retry. # # @raises [ ConnectionFailure ] When no primary node can be found # # @return [ Object ] The result of the yield. # # @since 1.0.0 - def with_primary(retry_on_failure = true, &block) + def with_primary(retries = max_retries, &block) if node = nodes.find(&:primary?) begin node.ensure_primary do return yield node.apply_auth(auth) end @@ -153,14 +206,15 @@ # Fall through to the code below if our connection was dropped or the # node is no longer the primary. end end - if retry_on_failure + if retries > 0 # We couldn't find a primary node, so refresh the list and try again. + sleep(retry_interval) refresh - with_primary(false, &block) + with_primary(retries - 1, &block) else raise( Errors::ConnectionFailure, "Could not connect to a primary node for replica set #{inspect}" ) @@ -173,19 +227,18 @@ # @example Yield the secondary to the block. # cluster.with_secondary do |node| # # ... # end # - # @param [ true, false ] retry_on_failure Whether to retry if an error was - # raised. + # @param [ Integer ] retries The number of times to retry. # # @raises [ ConnectionFailure ] When no primary node can be found # # @return [ Object ] The result of the yield. # # @since 1.0.0 - def with_secondary(retry_on_failure = true, &block) + def with_secondary(retries = max_retries, &block) available_nodes = nodes.shuffle!.partition(&:secondary?).flatten while node = available_nodes.shift begin return yield node.apply_auth(auth) @@ -193,14 +246,15 @@ # That node's no good, so let's try the next one. next end end - if retry_on_failure + if retries > 0 # We couldn't find a secondary or primary node, so refresh the list and # try again. + sleep(retry_interval) refresh - with_secondary(false, &block) + with_secondary(retries - 1, &block) else raise( Errors::ConnectionFailure, "Could not connect to any secondary or primary nodes for replica set #{inspect}" )