ReplSetConnection updates
This commit is contained in:
parent
08b7cddc81
commit
27b410f869
|
@ -92,47 +92,18 @@ module Mongo
|
|||
#
|
||||
# @core connections
|
||||
def initialize(host=nil, port=nil, options={})
|
||||
@auths = options.fetch(:auths, [])
|
||||
|
||||
@host_to_try = format_pair(host, port)
|
||||
|
||||
# Host and port of current master.
|
||||
@host = @port = nil
|
||||
|
||||
# Lock for request ids.
|
||||
@id_lock = Mutex.new
|
||||
|
||||
# Pool size and timeout.
|
||||
@pool_size = options[:pool_size] || 1
|
||||
@timeout = options[:timeout] || 5.0
|
||||
|
||||
# Mutex for synchronizing pool access
|
||||
@connection_mutex = Mutex.new
|
||||
|
||||
# Global safe option. This is false by default.
|
||||
@safe = options[:safe] || false
|
||||
|
||||
# Create a mutex when a new key, in this case a socket,
|
||||
# is added to the hash.
|
||||
@safe_mutexes = Hash.new { |h, k| h[k] = Mutex.new }
|
||||
|
||||
# Condition variable for signal and wait
|
||||
@queue = ConditionVariable.new
|
||||
|
||||
# slave_ok can be true only if one node is specified
|
||||
@slave_ok = options[:slave_ok]
|
||||
|
||||
@primary = nil
|
||||
|
||||
# Connection pool for primay node
|
||||
@primary_pool = nil
|
||||
|
||||
@logger = options[:logger] || nil
|
||||
|
||||
should_connect = options.fetch(:connect, true)
|
||||
connect if should_connect
|
||||
setup(options)
|
||||
end
|
||||
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# Initialize a connection to a MongoDB replica set using an array of seed nodes.
|
||||
|
@ -160,19 +131,10 @@ module Mongo
|
|||
#
|
||||
# @deprecated
|
||||
def self.multi(nodes, opts={})
|
||||
unless nodes.length > 0 && nodes.all? {|n| n.is_a? Array}
|
||||
raise MongoArgumentError, "Connection.multi requires at least one node to be specified."
|
||||
end
|
||||
warn "Connection.multi is now deprecated. Please use ReplSetConnection.new instead."
|
||||
|
||||
# Block returns an array, the first element being an array of nodes and the second an array
|
||||
# of authorizations for the database.
|
||||
new(nil, nil, opts) do |con|
|
||||
nodes.map do |node|
|
||||
con.instance_variable_set(:@replica_set, true)
|
||||
con.instance_variable_set(:@read_secondary, true) if opts[:read_secondary]
|
||||
con.pair_val_to_connection(node)
|
||||
end
|
||||
end
|
||||
nodes << opts
|
||||
ReplSetConnection.new(*nodes)
|
||||
end
|
||||
|
||||
# Initialize a connection to MongoDB using the MongoDB URI spec:
|
||||
|
@ -191,6 +153,8 @@ module Mongo
|
|||
elsif nodes.length > 1
|
||||
nodes << opts
|
||||
ReplSetConnection.new(*nodes)
|
||||
else
|
||||
raise MongoArgumentError, "No nodes specified. Please ensure that you've provided at least one node."
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -500,40 +464,8 @@ module Mongo
|
|||
@primary_pool = nil
|
||||
end
|
||||
|
||||
## Configuration helper methods
|
||||
|
||||
# Returns a host-port pair.
|
||||
#
|
||||
# @return [Array]
|
||||
#
|
||||
# @private
|
||||
def format_pair(host, port)
|
||||
case host
|
||||
when String
|
||||
[host, port ? port.to_i : DEFAULT_PORT]
|
||||
when nil
|
||||
['localhost', DEFAULT_PORT]
|
||||
end
|
||||
end
|
||||
|
||||
# Convert an argument containing a host name string and a
|
||||
# port number integer into a [host, port] pair array.
|
||||
#
|
||||
# @private
|
||||
def pair_val_to_connection(a)
|
||||
case a
|
||||
when nil
|
||||
['localhost', DEFAULT_PORT]
|
||||
when String
|
||||
[a, DEFAULT_PORT]
|
||||
when Integer
|
||||
['localhost', a]
|
||||
when Array
|
||||
a
|
||||
end
|
||||
end
|
||||
|
||||
# Checkout a socket for reading (i.e., a secondary node).
|
||||
# Checkout a socket for reading (i.e., a secondary node).
|
||||
def checkout_reader
|
||||
connect unless connected?
|
||||
|
||||
|
@ -567,6 +499,77 @@ module Mongo
|
|||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Generic initialization code.
|
||||
# @protected
|
||||
def setup(options)
|
||||
# Authentication objects
|
||||
@auths = options.fetch(:auths, [])
|
||||
|
||||
# Lock for request ids.
|
||||
@id_lock = Mutex.new
|
||||
|
||||
# Pool size and timeout.
|
||||
@pool_size = options[:pool_size] || 1
|
||||
@timeout = options[:timeout] || 5.0
|
||||
|
||||
# Mutex for synchronizing pool access
|
||||
@connection_mutex = Mutex.new
|
||||
|
||||
# Global safe option. This is false by default.
|
||||
@safe = options[:safe] || false
|
||||
|
||||
# Create a mutex when a new key, in this case a socket,
|
||||
# is added to the hash.
|
||||
@safe_mutexes = Hash.new { |h, k| h[k] = Mutex.new }
|
||||
|
||||
# Condition variable for signal and wait
|
||||
@queue = ConditionVariable.new
|
||||
|
||||
# Connection pool for primay node
|
||||
@primary = nil
|
||||
@primary_pool = nil
|
||||
|
||||
@logger = options[:logger] || nil
|
||||
|
||||
should_connect = options.fetch(:connect, true)
|
||||
connect if should_connect
|
||||
end
|
||||
|
||||
## Configuration helper methods
|
||||
|
||||
# Returns a host-port pair.
|
||||
#
|
||||
# @return [Array]
|
||||
#
|
||||
# @private
|
||||
def format_pair(host, port)
|
||||
case host
|
||||
when String
|
||||
[host, port ? port.to_i : DEFAULT_PORT]
|
||||
when nil
|
||||
['localhost', DEFAULT_PORT]
|
||||
end
|
||||
end
|
||||
|
||||
# Convert an argument containing a host name string and a
|
||||
# port number integer into a [host, port] pair array.
|
||||
#
|
||||
# @private
|
||||
def pair_val_to_connection(a)
|
||||
case a
|
||||
when nil
|
||||
['localhost', DEFAULT_PORT]
|
||||
when String
|
||||
[a, DEFAULT_PORT]
|
||||
when Integer
|
||||
['localhost', a]
|
||||
when Array
|
||||
a
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# If a ConnectionFailure is raised, this method will be called
|
||||
|
@ -584,7 +587,7 @@ module Mongo
|
|||
# apply any saved authentication.
|
||||
# TODO: simplify
|
||||
def is_primary?(config)
|
||||
config && (config['ismaster'] == 1 || config['ismaster'] == true) || !@replica_set && @slave_ok
|
||||
config && (config['ismaster'] == 1 || config['ismaster'] == true) || @slave_ok
|
||||
end
|
||||
|
||||
def check_is_master(node)
|
||||
|
|
|
@ -19,19 +19,25 @@
|
|||
module Mongo
|
||||
|
||||
# Instantiates and manages connections to MongoDB.
|
||||
class ReplSetConnection
|
||||
class ReplSetConnection < Connection
|
||||
attr_reader :nodes, :secondaries, :arbiters, :read_pool, :secondary_pools
|
||||
|
||||
def initialize(*args)
|
||||
|
||||
if args.last.is_a?(Hash)
|
||||
options = args.pop
|
||||
opts = args.pop
|
||||
else
|
||||
opts = {}
|
||||
end
|
||||
|
||||
unless args.length > 0
|
||||
raise MongoArgumentError, "A ReplSetConnection requires at least one node."
|
||||
end
|
||||
|
||||
# Get seed nodes
|
||||
@nodes = args
|
||||
|
||||
# Replica set name
|
||||
@replica_set_name = options[:rs_name]
|
||||
@replica_set = opts[:rs_name]
|
||||
|
||||
# Cache the various node types when connecting to a replica set.
|
||||
@secondaries = []
|
||||
|
@ -41,7 +47,10 @@ module Mongo
|
|||
@secondary_pools = []
|
||||
@read_pool = nil
|
||||
|
||||
super
|
||||
# Are we allowing reads from secondaries?
|
||||
@read_secondary = opts.fetch(:read_secondary, false)
|
||||
|
||||
setup(opts)
|
||||
end
|
||||
|
||||
# Create a new socket and attempt to connect to master.
|
||||
|
@ -86,13 +95,14 @@ module Mongo
|
|||
|
||||
# If a ConnectionFailure is raised, this method will be called
|
||||
# to close the connection and reset connection values.
|
||||
# TODO: what's the point of this method?
|
||||
def reset_connection
|
||||
super
|
||||
@secondaries = []
|
||||
@secondary_pools = []
|
||||
@arbiters = []
|
||||
@nodes_tried = []
|
||||
@nodes_to_try = []
|
||||
@nodes_tried = []
|
||||
@nodes_to_try = []
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -124,7 +134,12 @@ module Mongo
|
|||
config
|
||||
end
|
||||
|
||||
|
||||
# Primary, when connecting to a replica can, can only be a true primary node.
|
||||
# (And not a slave, which is possible when connecting with the standard
|
||||
# Connection class.
|
||||
def is_primary?(config)
|
||||
config && (config['ismaster'] == 1 || config['ismaster'] == true)
|
||||
end
|
||||
|
||||
# Pick a node randomly from the set of possible secondaries.
|
||||
def pick_secondary_for_read
|
||||
|
@ -135,15 +150,15 @@ module Mongo
|
|||
|
||||
# Make sure that we're connected to the expected replica set.
|
||||
def check_set_name(config, socket)
|
||||
if @replica_set_name
|
||||
if @replica_set
|
||||
config = self['admin'].command({:replSetGetStatus => 1},
|
||||
:sock => socket, :check_response => false)
|
||||
|
||||
if !Mongo::Support.ok?(config)
|
||||
raise ReplicaSetConnectionError, config['errmsg']
|
||||
elsif config['set'] != @replica_set_name
|
||||
elsif config['set'] != @replica_set
|
||||
raise ReplicaSetConnectionError,
|
||||
"Attempting to connect to replica set '#{config['set']}' but expected '#{@replica_set_name}'"
|
||||
"Attempting to connect to replica set '#{config['set']}' but expected '#{@replica_set}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,15 +9,15 @@ class ConnectTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def test_connect_bad_name
|
||||
assert_raise_error(ReplicaSetConnectionError, "expected 'wrong-repl-set-name'") do
|
||||
Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]],
|
||||
:rs_name => "wrong-repl-set-name")
|
||||
assert_raise_error(ReplicaSetReplSetConnectionError, "expected 'wrong-repl-set-name'") do
|
||||
ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2], :rs_name => "wrong-repl-set-name")
|
||||
end
|
||||
end
|
||||
|
||||
def test_connect
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]],
|
||||
:name => "foo")
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2], :name => "foo")
|
||||
assert @conn.connected?
|
||||
end
|
||||
|
||||
|
@ -25,7 +25,8 @@ class ConnectTest < Test::Unit::TestCase
|
|||
puts "Please kill the node at #{TEST_PORT}."
|
||||
gets
|
||||
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2]])
|
||||
assert @conn.connected?
|
||||
end
|
||||
|
||||
|
@ -33,7 +34,8 @@ class ConnectTest < Test::Unit::TestCase
|
|||
puts "Please kill the node at #{TEST_PORT + 1}."
|
||||
gets
|
||||
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2]])
|
||||
assert @conn.connected?
|
||||
end
|
||||
|
||||
|
@ -41,7 +43,8 @@ class ConnectTest < Test::Unit::TestCase
|
|||
puts "Please kill the node at #{TEST_PORT + 2}."
|
||||
gets
|
||||
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2]])
|
||||
assert @conn.connected?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,8 @@ class ReplicaSetCountTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2])
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
@coll = @db.collection("test-sets")
|
||||
|
|
|
@ -9,7 +9,8 @@ class ReplicaSetInsertTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2]])
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
@coll = @db.collection("test-sets")
|
||||
|
|
|
@ -9,7 +9,8 @@ class ReplicaSetNodeTypeTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2])
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
@coll = @db.collection("test-sets")
|
||||
|
|
|
@ -9,8 +9,8 @@ class ReplicaSetPooledInsertTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]],
|
||||
:pool_size => 10, :timeout => 5)
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2], :pool_size => 10, :timeout => 5)
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
@coll = @db.collection("test-sets")
|
||||
|
|
|
@ -9,7 +9,7 @@ class ReplicaSetQuerySecondariesTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT]], :read_secondary => true)
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], :read_secondary => true)
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
@coll = @db.collection("test-sets", :safe => {:w => 2, :wtimeout => 100})
|
||||
|
|
|
@ -9,7 +9,8 @@ class ReplicaSetQueryTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2])
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
@coll = @db.collection("test-sets")
|
||||
|
|
|
@ -8,11 +8,13 @@ class ReplicaSetAckTest < Test::Unit::TestCase
|
|||
include Mongo
|
||||
|
||||
def setup
|
||||
@conn = Mongo::Connection.multi([[TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1], [TEST_HOST, TEST_PORT + 2]])
|
||||
@conn = ReplSetConnection.multi([TEST_HOST, TEST_PORT], [TEST_HOST, TEST_PORT + 1],
|
||||
[TEST_HOST, TEST_PORT + 2])
|
||||
|
||||
master = [@conn.primary_pool.host, @conn.primary_pool.port]
|
||||
|
||||
@slave1 = Mongo::Connection.new(@conn.secondary_pools[0].host, @conn.secondary_pools[0].port, :slave_ok => true)
|
||||
@slave1 = Connection.new(@conn.secondary_pools[0].host,
|
||||
@conn.secondary_pools[0].port, :slave_ok => true)
|
||||
|
||||
@db = @conn.db(MONGO_TEST_DB)
|
||||
@db.drop_collection("test-sets")
|
||||
|
@ -37,7 +39,6 @@ class ReplicaSetAckTest < Test::Unit::TestCase
|
|||
assert @col.insert({:foo => "0" * 10000}, :safe => {:w => 2, :wtimeout => 1000})
|
||||
assert_equal 2, @slave1[MONGO_TEST_DB]["test-sets"].count
|
||||
|
||||
|
||||
assert @col.update({:baz => "bar"}, {:baz => "foo"}, :safe => {:w => 2, :wtimeout => 1000})
|
||||
assert @slave1[MONGO_TEST_DB]["test-sets"].find_one({:baz => "foo"})
|
||||
|
||||
|
|
|
@ -1,181 +1,82 @@
|
|||
require './test/test_helper'
|
||||
include Mongo
|
||||
|
||||
#class ConnectionTest < Test::Unit::TestCase
|
||||
# context "Initialization: " do
|
||||
# setup do
|
||||
# def new_mock_socket(host='localhost', port=27017)
|
||||
# socket = Object.new
|
||||
# socket.stubs(:setsockopt).with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
||||
# socket.stubs(:close)
|
||||
# socket
|
||||
# end
|
||||
#
|
||||
# def new_mock_db
|
||||
# db = Object.new
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# context "given a single node" do
|
||||
# setup do
|
||||
# @conn = Connection.new('localhost', 27017, :connect => false)
|
||||
# TCPSocket.stubs(:new).returns(new_mock_socket)
|
||||
#
|
||||
# admin_db = new_mock_db
|
||||
# admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
|
||||
# @conn.expects(:[]).with('admin').returns(admin_db)
|
||||
# @conn.connect
|
||||
# end
|
||||
#
|
||||
# should "set localhost and port to master" do
|
||||
# assert_equal 'localhost', @conn.primary_pool.host
|
||||
# assert_equal 27017, @conn.primary_pool.port
|
||||
# end
|
||||
#
|
||||
# should "set connection pool to 1" do
|
||||
# assert_equal 1, @conn.primary_pool.size
|
||||
# end
|
||||
#
|
||||
# should "default slave_ok to false" do
|
||||
# assert !@conn.slave_ok?
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# context "connecting to a replica set" do
|
||||
# setup do
|
||||
# TCPSocket.stubs(:new).returns(new_mock_socket('localhost', 27017))
|
||||
# @conn = Connection.multi([['localhost', 27017]], :connect => false, :read_secondary => true)
|
||||
#
|
||||
# admin_db = new_mock_db
|
||||
# @hosts = ['localhost:27018', 'localhost:27019', 'localhost:27020']
|
||||
#
|
||||
# admin_db.stubs(:command).returns({'ok' => 1, 'ismaster' => 1, 'hosts' => @hosts}).
|
||||
# then.returns({'ok' => 1, 'ismaster' => 0, 'hosts' => @hosts, 'secondary' => 1}).
|
||||
# then.returns({'ok' => 1, 'ismaster' => 0, 'hosts' => @hosts, 'secondary' => 1}).
|
||||
# then.returns({'ok' => 1, 'ismaster' => 0, 'arbiterOnly' => 1})
|
||||
#
|
||||
# @conn.stubs(:[]).with('admin').returns(admin_db)
|
||||
# @conn.connect
|
||||
# end
|
||||
#
|
||||
# should "store the hosts returned from the ismaster command" do
|
||||
# assert_equal 'localhost', @conn.primary_pool.host
|
||||
# assert_equal 27017, @conn.primary_pool.port
|
||||
#
|
||||
# assert_equal 'localhost', @conn.secondary_pools[0].host
|
||||
# assert_equal 27018, @conn.secondary_pools[0].port
|
||||
#
|
||||
# assert_equal 'localhost', @conn.secondary_pools[1].host
|
||||
# assert_equal 27019, @conn.secondary_pools[1].port
|
||||
#
|
||||
# assert_equal 2, @conn.secondary_pools.length
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# context "connecting to a replica set and providing seed nodes" do
|
||||
# setup do
|
||||
# TCPSocket.stubs(:new).returns(new_mock_socket)
|
||||
# @conn = Connection.multi([['localhost', 27017], ['localhost', 27019]], :connect => false)
|
||||
#
|
||||
# admin_db = new_mock_db
|
||||
# @hosts = ['localhost:27017', 'localhost:27018', 'localhost:27019']
|
||||
# admin_db.stubs(:command).returns({'ok' => 1, 'ismaster' => 1, 'hosts' => @hosts})
|
||||
# @conn.stubs(:[]).with('admin').returns(admin_db)
|
||||
# @conn.connect
|
||||
# end
|
||||
#
|
||||
# should "not store any hosts redundantly" do
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# context "initializing a paired connection" do
|
||||
# should "require left and right nodes" do
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.multi(['localhost', 27018], :connect => false)
|
||||
# end
|
||||
#
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.multi(['localhost', 27018], :connect => false)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# should "store both nodes" do
|
||||
# @conn = Connection.multi([['localhost', 27017], ['localhost', 27018]], :connect => false)
|
||||
#
|
||||
# assert_equal ['localhost', 27017], @conn.nodes[0]
|
||||
# assert_equal ['localhost', 27018], @conn.nodes[1]
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# context "initializing with a mongodb uri" do
|
||||
# should "parse a simple uri" do
|
||||
# @conn = Connection.from_uri("mongodb://localhost", :connect => false)
|
||||
# assert_equal ['localhost', 27017], @conn.primary
|
||||
# end
|
||||
#
|
||||
# should "allow a complex host names" do
|
||||
# host_name = "foo.bar-12345.org"
|
||||
# @conn = Connection.from_uri("mongodb://#{host_name}", :connect => false)
|
||||
# assert_equal [host_name, 27017], @conn.primary
|
||||
# end
|
||||
#
|
||||
# should "parse a uri specifying multiple nodes" do
|
||||
# #@conn = Connection.from_uri("mongodb://localhost:27017,mydb.com:27018", :connect => false)
|
||||
# #assert_equal ['localhost', 27017], @conn.nodes[0]
|
||||
# #assert_equal ['mydb.com', 27018], @conn.nodes[1]
|
||||
# end
|
||||
#
|
||||
# should "parse a uri specifying multiple nodes with auth" do
|
||||
# #@conn = Connection.from_uri("mongodb://kyle:s3cr3t@localhost:27017/app,mickey:m0u5e@mydb.com:27018/dsny", :connect => false)
|
||||
# #assert_equal ['localhost', 27017], @conn.nodes[0]
|
||||
# #assert_equal ['mydb.com', 27018], @conn.nodes[1]
|
||||
# #auth_hash = {'username' => 'kyle', 'password' => 's3cr3t', 'db_name' => 'app'}
|
||||
# #assert_equal auth_hash, @conn.auths[0]
|
||||
# #auth_hash = {'username' => 'mickey', 'password' => 'm0u5e', 'db_name' => 'dsny'}
|
||||
# #assert_equal auth_hash, @conn.auths[1]
|
||||
# end
|
||||
#
|
||||
# should "parse a uri with a hyphen & underscore in the username or password" do
|
||||
# @conn = Connection.from_uri("mongodb://hyphen-user_name:p-s_s@localhost:27017/db", :connect => false)
|
||||
# assert_equal ['localhost', 27017], @conn.nodes[0]
|
||||
# auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
|
||||
# assert_equal auth_hash, @conn.auths[0]
|
||||
# end
|
||||
#
|
||||
# should "attempt to connect" do
|
||||
# TCPSocket.stubs(:new).returns(new_mock_socket)
|
||||
# @conn = Connection.from_uri("mongodb://localhost", :connect => false)
|
||||
#
|
||||
# admin_db = new_mock_db
|
||||
# admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
|
||||
# @conn.expects(:[]).with('admin').returns(admin_db)
|
||||
# @conn.expects(:apply_saved_authentication)
|
||||
# @conn.connect
|
||||
# end
|
||||
#
|
||||
# should "raise an error on invalid uris" do
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.from_uri("mongo://localhost", :connect => false)
|
||||
# end
|
||||
#
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.from_uri("mongodb://localhost:abc", :connect => false)
|
||||
# end
|
||||
#
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.from_uri("mongodb://localhost:27017, my.db.com:27018, ", :connect => false)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# should "require all of username, password, and database if any one is specified" do
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.from_uri("mongodb://localhost/db", :connect => false)
|
||||
# end
|
||||
#
|
||||
# assert_raise MongoArgumentError do
|
||||
# Connection.from_uri("mongodb://kyle:password@localhost", :connect => false)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#end
|
||||
class ReplSetConnectionTest < Test::Unit::TestCase
|
||||
context "Initialization: " do
|
||||
setup do
|
||||
def new_mock_socket(host='localhost', port=27017)
|
||||
socket = Object.new
|
||||
socket.stubs(:setsockopt).with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
||||
socket.stubs(:close)
|
||||
socket
|
||||
end
|
||||
|
||||
def new_mock_db
|
||||
db = Object.new
|
||||
end
|
||||
end
|
||||
|
||||
context "connecting to a replica set" do
|
||||
setup do
|
||||
TCPSocket.stubs(:new).returns(new_mock_socket('localhost', 27017))
|
||||
@conn = ReplSetConnection.new(['localhost', 27017], :connect => false, :read_secondary => true)
|
||||
|
||||
admin_db = new_mock_db
|
||||
@hosts = ['localhost:27018', 'localhost:27019', 'localhost:27020']
|
||||
|
||||
admin_db.stubs(:command).returns({'ok' => 1, 'ismaster' => 1, 'hosts' => @hosts}).
|
||||
then.returns({'ok' => 1, 'ismaster' => 0, 'hosts' => @hosts, 'secondary' => 1}).
|
||||
then.returns({'ok' => 1, 'ismaster' => 0, 'hosts' => @hosts, 'secondary' => 1}).
|
||||
then.returns({'ok' => 1, 'ismaster' => 0, 'arbiterOnly' => 1})
|
||||
|
||||
@conn.stubs(:[]).with('admin').returns(admin_db)
|
||||
@conn.connect
|
||||
end
|
||||
|
||||
should "store the hosts returned from the ismaster command" do
|
||||
assert_equal 'localhost', @conn.primary_pool.host
|
||||
assert_equal 27017, @conn.primary_pool.port
|
||||
|
||||
assert_equal 'localhost', @conn.secondary_pools[0].host
|
||||
assert_equal 27018, @conn.secondary_pools[0].port
|
||||
|
||||
assert_equal 'localhost', @conn.secondary_pools[1].host
|
||||
assert_equal 27019, @conn.secondary_pools[1].port
|
||||
|
||||
assert_equal 2, @conn.secondary_pools.length
|
||||
end
|
||||
end
|
||||
|
||||
context "connecting to a replica set and providing seed nodes" do
|
||||
setup do
|
||||
TCPSocket.stubs(:new).returns(new_mock_socket)
|
||||
@conn = ReplSetConnection.new(['localhost', 27017], ['localhost', 27019], :connect => false)
|
||||
|
||||
admin_db = new_mock_db
|
||||
@hosts = ['localhost:27017', 'localhost:27018', 'localhost:27019']
|
||||
admin_db.stubs(:command).returns({'ok' => 1, 'ismaster' => 1, 'hosts' => @hosts})
|
||||
@conn.stubs(:[]).with('admin').returns(admin_db)
|
||||
@conn.connect
|
||||
end
|
||||
end
|
||||
|
||||
context "initializing with a mongodb uri" do
|
||||
|
||||
should "parse a uri specifying multiple nodes" do
|
||||
@conn = Connection.from_uri("mongodb://localhost:27017,mydb.com:27018", :connect => false)
|
||||
assert_equal ['localhost', 27017], @conn.nodes[0]
|
||||
assert_equal ['mydb.com', 27018], @conn.nodes[1]
|
||||
end
|
||||
|
||||
should "parse a uri specifying multiple nodes with auth" do
|
||||
@conn = Connection.from_uri("mongodb://kyle:s3cr3t@localhost:27017/app,mickey:m0u5e@mydb.com:27018/dsny", :connect => false)
|
||||
assert_equal ['localhost', 27017], @conn.nodes[0]
|
||||
assert_equal ['mydb.com', 27018], @conn.nodes[1]
|
||||
auth_hash = {'username' => 'kyle', 'password' => 's3cr3t', 'db_name' => 'app'}
|
||||
assert_equal auth_hash, @conn.auths[0]
|
||||
auth_hash = {'username' => 'mickey', 'password' => 'm0u5e', 'db_name' => 'dsny'}
|
||||
assert_equal auth_hash, @conn.auths[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue