minor fixes and doc updates. :sync is default refresh mode.

This commit is contained in:
Kyle Banker 2011-09-15 18:44:02 -04:00
parent 3e3f05813a
commit 63c91af1b1
4 changed files with 51 additions and 24 deletions

View File

@ -15,10 +15,10 @@ cache the replica set topology as reported by the given seed node and use that i
### Read slaves ### Read slaves
If you want to read from a seconday node, you can pass :read_secondary => true to ReplSetConnection#new. If you want to read from a secondary node, you can pass :read => :secondary to ReplSetConnection#new.
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], ['n2.mydb.net', 27017], ['n3.mydb.net', 27017], @connection = ReplSetConnection.new(['n1.mydb.net', 27017], ['n2.mydb.net', 27017], ['n3.mydb.net', 27017],
:read_secondary => true) :read => :secondary)
A random secondary will be chosen to be read from. In a typical multi-process Ruby application, you'll have a good distribution of reads across secondary nodes. A random secondary will be chosen to be read from. In a typical multi-process Ruby application, you'll have a good distribution of reads across secondary nodes.
@ -32,6 +32,27 @@ If the client decides to retry, it's not guaranteed that another member of the r
The driver will essentially cycle through all known seed addresses until a node identifies itself as master. The driver will essentially cycle through all known seed addresses until a node identifies itself as master.
### Refresh mode
You can now specify a refresh mode and refresh interval for a replica set connection. This will help to ensure that
changes to a replica set's configuration are quickly reflected on the driver side. Refresh mode is
enabled in synchronous mode by default. Here's how to specify this explicitly:
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], :refresh_mode => :sync)
If you want to refresh to happen via a background thread, use the `:async` mode:
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], :refresh_mode => :async)
If you want to change the default refresh interval of 90 seconds, you can do so like this:
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], :refresh_mode => :async,
:refresh_interval => 60)
You can also disable refresh mode altogether:
@connection = ReplSetConnection.new(['n1.mydb.net', 27017], :refresh_mode => false)
### Recovery ### Recovery
Driver users may wish to wrap their database calls with failure recovery code. Here's one possibility, which will attempt to connection Driver users may wish to wrap their database calls with failure recovery code. Here's one possibility, which will attempt to connection

View File

@ -1,4 +1,4 @@
# Tailable in Ruby # Tailable cursors in Ruby
Tailable cursors are cursors that remain open even after they've returned Tailable cursors are cursors that remain open even after they've returned
a final result. This way, if more documents are added to a collection (i.e., a final result. This way, if more documents are added to a collection (i.e.,

View File

@ -24,7 +24,7 @@ module Mongo
class ReplSetConnection < Connection class ReplSetConnection < Connection
attr_reader :nodes, :secondaries, :arbiters, :secondary_pools, attr_reader :nodes, :secondaries, :arbiters, :secondary_pools,
:replica_set_name, :read_pool, :seeds, :tags_to_pools, :replica_set_name, :read_pool, :seeds, :tags_to_pools,
:refresh_interval, :background_refresh :refresh_interval, :refresh_mode
# Create a connection to a MongoDB replica set. # Create a connection to a MongoDB replica set.
# #
@ -46,7 +46,7 @@ module Mongo
# objects created from this connection object. If +:secondary+ is chosen, reads will be sent # objects created from this connection object. If +:secondary+ is chosen, reads will be sent
# to one of the closest available secondary nodes. If a secondary node cannot be located, the # to one of the closest available secondary nodes. If a secondary node cannot be located, the
# read will be sent to the primary. # read will be sent to the primary.
# @option options [Logger, #debug] :logger (nil) Logger instance to receive driver operation log. # @option options [Logger] :logger (nil) Logger instance to receive driver operation log.
# @option options [Integer] :pool_size (1) The maximum number of socket connections allowed per # @option options [Integer] :pool_size (1) The maximum number of socket connections allowed per
# connection pool. Note: this setting is relevant only for multi-threaded applications. # connection pool. Note: this setting is relevant only for multi-threaded applications.
# @option options [Float] :pool_timeout (5.0) When all of the connections a pool are checked out, # @option options [Float] :pool_timeout (5.0) When all of the connections a pool are checked out,
@ -57,15 +57,15 @@ module Mongo
# @option opts [Float] :connect_timeout (nil) The number of seconds to wait before timing out a # @option opts [Float] :connect_timeout (nil) The number of seconds to wait before timing out a
# connection attempt. # connection attempt.
# @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL. # @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
# @option opts [Boolean] :background_refresh (false) Set this to true to enable a background thread that # @option opts [Boolean] :refresh_mode (:sync) Set this to :async to enable a background thread that
# periodically updates the state of the connection. If, for example, you initially connect while a secondary # periodically updates the state of the connection. If, for example, you initially connect while a secondary
# is down, :background_refresh will reconnect to that secondary behind the scenes to # is down, this will reconnect to that secondary behind the scenes to
# prevent you from having to reconnect manually. If set to +false+, background refresh will happen # prevent you from having to reconnect manually. If set to :sync, refresh will happen
# synchronously. # synchronously. If +false+, no automatic refresh will occur unless there's a connection failure.
# @option opts [Integer] :refresh_interval (90) If :background_refresh is enabled, this is the number of seconds # @option opts [Integer] :refresh_interval (90) If :refresh_mode is enabled, this is the number of seconds
# that the background thread will sleep between calls to check the replica set's state. # between calls to check the replica set's state.
# @option opts [Boolean] :require_primary (true) If true, require a primary node for the connection # @option opts [Boolean] :require_primary (true) If true, require a primary node for the connection
# to succeed. Otherwise, connection will succeed as long as there's at least one secondary. # to succeed. Otherwise, connection will succeed as long as there's at least one secondary node.
# #
# @example Connect to a replica set and provide two seed nodes. Note that the number of seed nodes does # @example Connect to a replica set and provide two seed nodes. Note that the number of seed nodes does
# not have to be equal to the number of replica set members. The purpose of seed nodes is to permit # not have to be equal to the number of replica set members. The purpose of seed nodes is to permit
@ -120,9 +120,14 @@ module Mongo
@arbiters = [] @arbiters = []
# Refresh # Refresh
@background_refresh = opts.fetch(:background_refresh, false) @refresh_mode = opts.fetch(:refresh_mode, :sync)
@refresh_interval = opts[:refresh_interval] || 90 @refresh_interval = opts[:refresh_interval] || 90
if ![:sync, :async, false].include?(@refresh_mode)
raise MongoArgumentError,
"Refresh mode must be one of :sync, :async, or false."
end
# Are we allowing reads from secondaries? # Are we allowing reads from secondaries?
if opts[:read_secondary] if opts[:read_secondary]
warn ":read_secondary options has now been deprecated and will " + warn ":read_secondary options has now been deprecated and will " +
@ -165,14 +170,14 @@ module Mongo
# Initiate a connection to the replica set. # Initiate a connection to the replica set.
def connect def connect
log(:debug, "Connecting...") log(:info, "Connecting...")
sync_synchronize(:EX) do sync_synchronize(:EX) do
return if @connected return if @connected
manager = PoolManager.new(self, @seeds) manager = PoolManager.new(self, @seeds)
manager.connect manager.connect
update_config(manager) update_config(manager)
initiate_background_refresh initiate_refresh_mode
if @require_primary && @primary.nil? #TODO: in v2.0, we'll let this be optional and do a lazy connect. if @require_primary && @primary.nil? #TODO: in v2.0, we'll let this be optional and do a lazy connect.
raise ConnectionFailure, "Failed to connect to primary node." raise ConnectionFailure, "Failed to connect to primary node."
@ -210,7 +215,7 @@ module Mongo
return if sync_exclusive? return if sync_exclusive?
sync_synchronize(:EX) do sync_synchronize(:EX) do
log(:debug, "Refreshing...") log(:info, "Refreshing...")
@background_manager ||= PoolManager.new(self, @seeds) @background_manager ||= PoolManager.new(self, @seeds)
@background_manager.connect @background_manager.connect
update_config(@background_manager) update_config(@background_manager)
@ -220,11 +225,12 @@ module Mongo
end end
def connected? def connected?
@primary_pool || @read_pool !@primary_pool.nil? || !@read_pool.nil?
end end
# @deprecated # @deprecated
def connecting? def connecting?
warn "ReplSetConnection#connecting? is deprecated and will be removed in v2.0."
false false
end end
@ -333,8 +339,8 @@ module Mongo
private private
def initiate_background_refresh def initiate_refresh_mode
if @background_refresh if @refresh_mode == :async
return if @refresh_thread && @refresh_thread.alive? return if @refresh_thread && @refresh_thread.alive?
@refresh_thread = Thread.new do @refresh_thread = Thread.new do
while true do while true do
@ -342,9 +348,9 @@ module Mongo
refresh refresh
end end
end end
else
@last_refresh = Time.now
end end
@last_refresh = Time.now
end end
# Checkout a socket for reading (i.e., a secondary node). # Checkout a socket for reading (i.e., a secondary node).
@ -444,8 +450,8 @@ module Mongo
end end
# Refresh synchronously every @refresh_interval seconds # Refresh synchronously every @refresh_interval seconds
# if @background_refresh is false. # if synchronous refresh mode is enabled.
if !@background_refresh && if @refresh_mode == :sync &&
((Time.now - @last_refresh) > @refresh_interval) ((Time.now - @last_refresh) > @refresh_interval)
refresh refresh
end end

View File

@ -69,7 +69,7 @@ module Mongo
def inspect def inspect
"#<Mongo::Pool:0x#{self.object_id.to_s(16)} @host=#{@host} @port=#{port} " + "#<Mongo::Pool:0x#{self.object_id.to_s(16)} @host=#{@host} @port=#{port} " +
"@ping_time=#{ping_time} #{@checked_out.size}/#{@size} sockets available.>" "@ping_time=#{@ping_time} #{@checked_out.size}/#{@size} sockets available.>"
end end
def host_string def host_string