mongo 1.7.1 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +124 -111
- data/Rakefile +9 -325
- data/VERSION +1 -0
- data/bin/mongo_console +4 -4
- data/examples/admin.rb +43 -0
- data/examples/capped.rb +22 -0
- data/examples/cursor.rb +48 -0
- data/examples/gridfs.rb +44 -0
- data/examples/index_test.rb +126 -0
- data/examples/info.rb +31 -0
- data/examples/queries.rb +74 -0
- data/examples/replica_set.rb +26 -0
- data/examples/simple.rb +25 -0
- data/examples/strict.rb +35 -0
- data/examples/types.rb +36 -0
- data/{test/load → examples/web}/thin/load.rb +3 -1
- data/{test/load → examples/web}/unicorn/load.rb +5 -3
- data/lib/mongo.rb +8 -10
- data/lib/mongo/collection.rb +134 -114
- data/lib/mongo/cursor.rb +21 -14
- data/lib/mongo/db.rb +30 -28
- data/lib/mongo/exceptions.rb +1 -1
- data/lib/mongo/gridfs/grid.rb +8 -7
- data/lib/mongo/gridfs/grid_ext.rb +1 -1
- data/lib/mongo/gridfs/grid_file_system.rb +6 -5
- data/lib/mongo/gridfs/grid_io.rb +22 -19
- data/lib/mongo/legacy.rb +82 -0
- data/lib/mongo/{connection.rb → mongo_client.rb} +82 -61
- data/lib/mongo/{repl_set_connection.rb → mongo_replica_set_client.rb} +54 -39
- data/lib/mongo/{sharded_connection.rb → mongo_sharded_client.rb} +9 -9
- data/lib/mongo/networking.rb +25 -20
- data/lib/mongo/util/conversions.rb +1 -1
- data/lib/mongo/util/core_ext.rb +1 -1
- data/lib/mongo/util/logging.rb +20 -4
- data/lib/mongo/util/node.rb +16 -16
- data/lib/mongo/util/pool.rb +56 -27
- data/lib/mongo/util/pool_manager.rb +28 -27
- data/lib/mongo/util/server_version.rb +1 -1
- data/lib/mongo/util/sharding_pool_manager.rb +8 -8
- data/lib/mongo/util/ssl_socket.rb +1 -5
- data/lib/mongo/util/support.rb +24 -8
- data/lib/mongo/util/tcp_socket.rb +0 -4
- data/lib/mongo/util/uri_parser.rb +54 -38
- data/lib/mongo/util/write_concern.rb +67 -0
- data/mongo.gemspec +21 -32
- data/test/auxillary/{1.4_features.rb → 1.4_feature_test.rb} +4 -5
- data/test/auxillary/authentication_test.rb +18 -20
- data/test/auxillary/autoreconnect_test.rb +3 -5
- data/test/auxillary/fork_test.rb +5 -7
- data/test/auxillary/repl_set_auth_test.rb +13 -15
- data/test/auxillary/slave_connection_test.rb +8 -7
- data/test/auxillary/threaded_authentication_test.rb +15 -17
- data/test/bson/binary_test.rb +1 -1
- data/test/bson/bson_test.rb +60 -36
- data/test/bson/byte_buffer_test.rb +1 -1
- data/test/bson/hash_with_indifferent_access_test.rb +2 -2
- data/test/bson/json_test.rb +1 -2
- data/test/bson/object_id_test.rb +1 -2
- data/test/bson/ordered_hash_test.rb +1 -1
- data/test/bson/timestamp_test.rb +1 -1
- data/test/{collection_test.rb → functional/collection_test.rb} +57 -57
- data/test/{connection_test.rb → functional/connection_test.rb} +75 -89
- data/test/{conversions_test.rb → functional/conversions_test.rb} +1 -1
- data/test/{cursor_fail_test.rb → functional/cursor_fail_test.rb} +3 -29
- data/test/{cursor_message_test.rb → functional/cursor_message_test.rb} +1 -1
- data/test/{cursor_test.rb → functional/cursor_test.rb} +5 -1
- data/test/{db_api_test.rb → functional/db_api_test.rb} +8 -9
- data/test/{db_connection_test.rb → functional/db_connection_test.rb} +3 -5
- data/test/{db_test.rb → functional/db_test.rb} +13 -13
- data/test/{grid_file_system_test.rb → functional/grid_file_system_test.rb} +2 -2
- data/test/{grid_io_test.rb → functional/grid_io_test.rb} +6 -6
- data/test/{grid_test.rb → functional/grid_test.rb} +4 -10
- data/test/{pool_test.rb → functional/pool_test.rb} +1 -1
- data/test/functional/safe_test.rb +84 -0
- data/test/{support_test.rb → functional/support_test.rb} +1 -1
- data/test/{threading_test.rb → functional/threading_test.rb} +9 -9
- data/test/{timeout_test.rb → functional/timeout_test.rb} +1 -1
- data/test/{uri_test.rb → functional/uri_test.rb} +1 -1
- data/test/functional/write_concern_test.rb +104 -0
- data/test/replica_set/basic_test.rb +139 -0
- data/test/replica_set/client_test.rb +255 -0
- data/test/replica_set/complex_connect_test.rb +62 -0
- data/test/replica_set/connection_test.rb +255 -0
- data/test/{replica_sets → replica_set}/count_test.rb +17 -14
- data/test/replica_set/cursor_test.rb +75 -0
- data/test/{replica_sets → replica_set}/insert_test.rb +19 -16
- data/test/replica_set/query_test.rb +64 -0
- data/test/replica_set/refresh_test.rb +153 -0
- data/test/{replica_sets → replica_set}/replication_ack_test.rb +21 -17
- data/test/sharded_cluster/basic_test.rb +31 -50
- data/test/support/hash_with_indifferent_access.rb +1 -1
- data/test/test_helper.rb +56 -9
- data/test/threading/threading_with_large_pool_test.rb +8 -8
- data/test/tools/mongo_config.rb +270 -58
- data/test/tools/mongo_config_test.rb +146 -0
- data/test/unit/client_test.rb +230 -0
- data/test/unit/collection_test.rb +45 -32
- data/test/unit/connection_test.rb +82 -74
- data/test/unit/cursor_test.rb +14 -6
- data/test/unit/db_test.rb +8 -8
- data/test/unit/grid_test.rb +11 -11
- data/test/unit/node_test.rb +24 -24
- data/test/unit/pool_manager_test.rb +13 -13
- data/test/unit/pool_test.rb +1 -1
- data/test/unit/read_test.rb +21 -26
- data/test/unit/safe_test.rb +52 -33
- data/test/unit/util_test.rb +55 -0
- data/test/unit/write_concern_test.rb +161 -0
- metadata +158 -171
- data/docs/CREDITS.md +0 -123
- data/docs/FAQ.md +0 -116
- data/docs/GRID_FS.md +0 -158
- data/docs/HISTORY.md +0 -392
- data/docs/READ_PREFERENCE.md +0 -99
- data/docs/RELEASES.md +0 -54
- data/docs/REPLICA_SETS.md +0 -113
- data/docs/TAILABLE_CURSORS.md +0 -51
- data/docs/TUTORIAL.md +0 -356
- data/docs/WRITE_CONCERN.md +0 -31
- data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
- data/lib/mongo/version.rb +0 -3
- data/test/bson/test_helper.rb +0 -30
- data/test/replica_sets/basic_test.rb +0 -119
- data/test/replica_sets/complex_connect_test.rb +0 -57
- data/test/replica_sets/complex_read_preference_test.rb +0 -237
- data/test/replica_sets/connect_test.rb +0 -156
- data/test/replica_sets/cursor_test.rb +0 -70
- data/test/replica_sets/pooled_insert_test.rb +0 -57
- data/test/replica_sets/query_test.rb +0 -50
- data/test/replica_sets/read_preference_test.rb +0 -234
- data/test/replica_sets/refresh_test.rb +0 -156
- data/test/replica_sets/refresh_with_threads_test.rb +0 -60
- data/test/replica_sets/rs_test_helper.rb +0 -39
- data/test/safe_test.rb +0 -68
- data/test/sharded_cluster/mongo_config_test.rb +0 -126
- data/test/sharded_cluster/sc_test_helper.rb +0 -39
- data/test/tools/repl_set_manager.rb +0 -418
data/docs/WRITE_CONCERN.md
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# Write Concern in Ruby
|
2
|
-
|
3
|
-
## Setting the write concern
|
4
|
-
|
5
|
-
Write concern is set using the `:safe` option. There are several possible options:
|
6
|
-
|
7
|
-
@collection.save({:doc => 'foo'}, :safe => true)
|
8
|
-
@collection.save({:doc => 'foo'}, :safe => {:w => 2})
|
9
|
-
@collection.save({:doc => 'foo'}, :safe => {:w => 2, :wtimeout => 200})
|
10
|
-
@collection.save({:doc => 'foo'}, :safe => {:w => 2, :wtimeout => 200, :j => true})
|
11
|
-
|
12
|
-
The first, `true`, simply indicates that we should request a response from the server to ensure that no errors have occurred. The second, `{:w => 2}`, forces the server to wait until at least two servers have recorded the write. The third does the same but will time out if the replication can't be completed in 200 milliseconds.
|
13
|
-
Setting a value for `wtimeout` is encouraged.
|
14
|
-
|
15
|
-
Finally, the fourth example forces the journal to sync to disk if journaling is enabled.
|
16
|
-
|
17
|
-
## Write concern inheritance
|
18
|
-
|
19
|
-
The Ruby driver allows you to set write concern on each of four levels: the connection, database, collection, and write operation.
|
20
|
-
Objects will inherit the default write concern from their parents. Thus, if you set a write concern of `{:w => 1}` when creating
|
21
|
-
a new connection, then all databases and collections created from that connection will inherit the same setting. See this code example:
|
22
|
-
|
23
|
-
@con = Mongo::Connection.new('localhost', 27017, :safe => {:w => 2})
|
24
|
-
@db = @con['test']
|
25
|
-
@collection = @db['foo']
|
26
|
-
@collection.save({:name => 'foo'})
|
27
|
-
|
28
|
-
@collection.save({:name => 'bar'}, :safe => false)
|
29
|
-
|
30
|
-
Here, the first call to Collection#save will use the inherited write concern, `{:w => 2}`. But notice that the second call
|
31
|
-
to Collection#save overrides this setting.
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# --
|
4
|
-
# Copyright (C) 2008-2011 10gen Inc.
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
# ++
|
18
|
-
|
19
|
-
module Mongo
|
20
|
-
class GridIO
|
21
|
-
|
22
|
-
# This fixes a comparson issue in JRuby 1.9
|
23
|
-
def get_md5
|
24
|
-
md5_command = BSON::OrderedHash.new
|
25
|
-
md5_command['filemd5'] = @files_id
|
26
|
-
md5_command['root'] = @fs_name
|
27
|
-
@server_md5 = @files.db.command(md5_command)['md5']
|
28
|
-
if @safe
|
29
|
-
@client_md5 = @local_md5.hexdigest
|
30
|
-
if @local_md5.to_s != @server_md5.to_s
|
31
|
-
raise GridMD5Failure, "File on server failed MD5 check"
|
32
|
-
end
|
33
|
-
else
|
34
|
-
@server_md5
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/mongo/version.rb
DELETED
data/test/bson/test_helper.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'bson')
|
2
|
-
require 'rubygems' if RUBY_VERSION < '1.9.0'
|
3
|
-
gem 'test-unit'
|
4
|
-
require 'test/unit'
|
5
|
-
|
6
|
-
def silently
|
7
|
-
warn_level = $VERBOSE
|
8
|
-
$VERBOSE = nil
|
9
|
-
result = yield
|
10
|
-
$VERBOSE = warn_level
|
11
|
-
result
|
12
|
-
end
|
13
|
-
|
14
|
-
require 'bson_ext/cbson' if !(RUBY_PLATFORM =~ /java/) && ENV['C_EXT']
|
15
|
-
|
16
|
-
class Test::Unit::TestCase
|
17
|
-
include BSON
|
18
|
-
|
19
|
-
def assert_raise_error(klass, message)
|
20
|
-
begin
|
21
|
-
yield
|
22
|
-
rescue => e
|
23
|
-
assert_equal klass, e.class
|
24
|
-
assert e.message.include?(message), "#{e.message} does not include #{message}."
|
25
|
-
else
|
26
|
-
flunk "Expected assertion #{klass} but none was raised."
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
require './test/replica_sets/rs_test_helper'
|
3
|
-
|
4
|
-
class BasicTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
ensure_rs
|
8
|
-
end
|
9
|
-
|
10
|
-
def teardown
|
11
|
-
@rs.restart_killed_nodes
|
12
|
-
@conn.close if defined?(@conn) && @conn
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_connect
|
16
|
-
@conn = ReplSetConnection.new(build_seeds(3), :name => @rs.name)
|
17
|
-
assert @conn.connected?
|
18
|
-
|
19
|
-
assert_equal @rs.primary, @conn.primary
|
20
|
-
assert_equal @rs.secondaries.sort, @conn.secondaries.sort
|
21
|
-
assert_equal @rs.arbiters.sort, @conn.arbiters.sort
|
22
|
-
|
23
|
-
@conn = ReplSetConnection.new(["#{@rs.host}:#{@rs.ports[1]}","#{@rs.host}:#{@rs.ports[0]}"],
|
24
|
-
:name => @rs.name)
|
25
|
-
assert @conn.connected?
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_multiple_concurrent_replica_set_connection
|
29
|
-
@conn1 = ReplSetConnection.new(build_seeds(3), :name => @rs.name)
|
30
|
-
@conn2 = ReplSetConnection.new(build_seeds(3), :name => @rs.name)
|
31
|
-
assert @conn1.connected?
|
32
|
-
assert @conn2.connected?
|
33
|
-
|
34
|
-
assert @conn1.manager != @conn2.manager
|
35
|
-
assert @conn1.local_manager != @conn2.local_manager
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_cache_original_seed_nodes
|
39
|
-
seeds = build_seeds(3) << "#{@rs.host}:19356"
|
40
|
-
@conn = ReplSetConnection.new(seeds, :name => @rs.name)
|
41
|
-
assert @conn.connected?
|
42
|
-
assert @conn.seeds.include?([@rs.host, 19356]), "Original seed nodes not cached!"
|
43
|
-
assert_equal [@rs.host, 19356], @conn.seeds.last, "Original seed nodes not cached!"
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_accessors
|
47
|
-
seeds = build_seeds(3)
|
48
|
-
args = {:name => @rs.name}
|
49
|
-
@conn = ReplSetConnection.new(seeds, args)
|
50
|
-
|
51
|
-
assert_equal @conn.host, @rs.primary[0]
|
52
|
-
assert_equal @conn.port, @rs.primary[1]
|
53
|
-
assert_equal @conn.host, @conn.primary_pool.host
|
54
|
-
assert_equal @conn.port, @conn.primary_pool.port
|
55
|
-
assert_equal 2, @conn.secondaries.length
|
56
|
-
assert_equal 0, @conn.arbiters.length
|
57
|
-
assert_equal 2, @conn.secondary_pools.length
|
58
|
-
assert_equal @rs.name, @conn.replica_set_name
|
59
|
-
assert @conn.secondary_pools.include?(@conn.read_pool(:secondary))
|
60
|
-
assert_equal 90, @conn.refresh_interval
|
61
|
-
assert_equal @conn.refresh_mode, false
|
62
|
-
end
|
63
|
-
|
64
|
-
context "Socket pools" do
|
65
|
-
context "checking out writers" do
|
66
|
-
setup do
|
67
|
-
seeds = build_seeds(3)
|
68
|
-
args = {:name => @rs.name}
|
69
|
-
@con = ReplSetConnection.new(seeds, args)
|
70
|
-
@coll = @con[MONGO_TEST_DB]['test-connection-exceptions']
|
71
|
-
end
|
72
|
-
|
73
|
-
should "close the connection on send_message for major exceptions" do
|
74
|
-
@con.expects(:checkout_writer).raises(SystemStackError)
|
75
|
-
@con.expects(:close)
|
76
|
-
begin
|
77
|
-
@coll.insert({:foo => "bar"})
|
78
|
-
rescue SystemStackError
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
should "close the connection on send_message_with_safe_check for major exceptions" do
|
83
|
-
@con.expects(:checkout_writer).raises(SystemStackError)
|
84
|
-
@con.expects(:close)
|
85
|
-
begin
|
86
|
-
@coll.insert({:foo => "bar"}, :safe => true)
|
87
|
-
rescue SystemStackError
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
should "close the connection on receive_message for major exceptions" do
|
92
|
-
@con.expects(:checkout_reader).raises(SystemStackError)
|
93
|
-
@con.expects(:close)
|
94
|
-
begin
|
95
|
-
@coll.find({}, :read => :primary).next
|
96
|
-
rescue SystemStackError
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context "checking out readers" do
|
102
|
-
setup do
|
103
|
-
seeds = build_seeds(3)
|
104
|
-
args = {:name => @rs.name}
|
105
|
-
@con = ReplSetConnection.new(seeds, args)
|
106
|
-
@coll = @con[MONGO_TEST_DB]['test-connection-exceptions']
|
107
|
-
end
|
108
|
-
|
109
|
-
should "close the connection on receive_message for major exceptions" do
|
110
|
-
@con.expects(:checkout_reader).raises(SystemStackError)
|
111
|
-
@con.expects(:close)
|
112
|
-
begin
|
113
|
-
@coll.find({}, :read => :secondary).next
|
114
|
-
rescue SystemStackError
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
require './test/replica_sets/rs_test_helper'
|
3
|
-
|
4
|
-
class ComplexConnectTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
def setup
|
7
|
-
ensure_rs
|
8
|
-
end
|
9
|
-
|
10
|
-
def teardown
|
11
|
-
@rs.restart_killed_nodes
|
12
|
-
@conn.close if defined?(@conn) && @conn
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_complex_connect
|
16
|
-
primary = Connection.new(@rs.host, @rs.ports[0])
|
17
|
-
|
18
|
-
@conn = ReplSetConnection.new([
|
19
|
-
"#{@rs.host}:#{@rs.ports[2]}",
|
20
|
-
"#{@rs.host}:#{@rs.ports[1]}",
|
21
|
-
"#{@rs.host}:#{@rs.ports[0]}",
|
22
|
-
])
|
23
|
-
|
24
|
-
version = @conn.server_version
|
25
|
-
|
26
|
-
@conn['test']['foo'].insert({:a => 1})
|
27
|
-
assert @conn['test']['foo'].find_one
|
28
|
-
|
29
|
-
config = primary['local']['system.replset'].find_one
|
30
|
-
config['version'] += 1
|
31
|
-
config['members'].delete_if do |member|
|
32
|
-
member['host'].include?(@rs.ports[2].to_s)
|
33
|
-
end
|
34
|
-
|
35
|
-
assert_raise ConnectionFailure do
|
36
|
-
primary['admin'].command({:replSetReconfig => config})
|
37
|
-
end
|
38
|
-
@rs.ensure_up
|
39
|
-
|
40
|
-
force_stepdown = BSON::OrderedHash.new
|
41
|
-
force_stepdown[:replSetStepDown] = 1
|
42
|
-
force_stepdown[:force] = true
|
43
|
-
|
44
|
-
assert_raise ConnectionFailure do
|
45
|
-
primary['admin'].command(force_stepdown)
|
46
|
-
end
|
47
|
-
|
48
|
-
# isMaster is currently broken in 2.1+ when called on removed nodes
|
49
|
-
if version < "2.1"
|
50
|
-
rescue_connection_failure do
|
51
|
-
assert @conn['test']['foo'].find_one
|
52
|
-
end
|
53
|
-
|
54
|
-
assert @conn['test']['foo'].find_one
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,237 +0,0 @@
|
|
1
|
-
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
require './test/replica_sets/rs_test_helper'
|
3
|
-
require 'logger'
|
4
|
-
|
5
|
-
# Tags for members:
|
6
|
-
# 0 => {"dc" => "ny", "rack" => "a", "db" => "main"}
|
7
|
-
# 1 => {"dc" => "ny", "rack" => "b", "db" => "main"}
|
8
|
-
# 2 => {"dc" => "sf", "rack" => "a", "db" => "main"}
|
9
|
-
|
10
|
-
class ComplexReadPreferenceTest < Test::Unit::TestCase
|
11
|
-
def setup
|
12
|
-
ensure_rs
|
13
|
-
|
14
|
-
# Insert data
|
15
|
-
conn = Connection.new(@rs.host, @rs.primary[1])
|
16
|
-
db = conn.db(MONGO_TEST_DB)
|
17
|
-
coll = db.collection("test-sets")
|
18
|
-
coll.save({:a => 20}, :safe => {:w => 2})
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_primary_with_tags
|
22
|
-
# Test specifying a tag set with default read preference of primary throws and error
|
23
|
-
conn = make_connection({:tag_sets => {"rack" => "a"}})
|
24
|
-
assert_raise_error MongoArgumentError, "Read preferecy :primary cannot be combined with tags" do
|
25
|
-
conn.read_pool
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_tags
|
30
|
-
return true if @rs.version < "2.1"
|
31
|
-
|
32
|
-
assert_read_pool(:primary, {}, 0)
|
33
|
-
assert_read_pool(:primary_preferred, {}, 0)
|
34
|
-
assert_read_pool(:secondary, {}, [1,2])
|
35
|
-
assert_read_pool(:secondary_preferred, {}, [1,2])
|
36
|
-
|
37
|
-
# Test tag_sets are ignored on primary
|
38
|
-
assert_read_pool(:primary_preferred,
|
39
|
-
{"rack" => "b"}, 0)
|
40
|
-
|
41
|
-
# Test single tag
|
42
|
-
assert_read_pool(:secondary,
|
43
|
-
{"rack" => "a"}, 2)
|
44
|
-
assert_read_pool(:secondary,
|
45
|
-
{"rack" => "b"}, 1)
|
46
|
-
assert_read_pool(:secondary,
|
47
|
-
{"db" => "main"}, [1, 2])
|
48
|
-
|
49
|
-
# Test multiple tags
|
50
|
-
assert_read_pool(:secondary,
|
51
|
-
{"db" => "main", "rack" => "a"}, 2)
|
52
|
-
assert_read_pool(:secondary,
|
53
|
-
{"dc" => "ny", "rack" => "b", "db" => "main"}, 1)
|
54
|
-
|
55
|
-
# Test multiple tags failing
|
56
|
-
assert_fail_pool(:secondary,
|
57
|
-
{"dc" => "ny", "rack" => "a"})
|
58
|
-
assert_fail_pool(:secondary,
|
59
|
-
{"dc" => "ny", "rack" => "b", "db" => "main", "xtra" => "?"})
|
60
|
-
|
61
|
-
# Test symbol is converted to string for key
|
62
|
-
assert_read_pool(:secondary,
|
63
|
-
{:db => "main", "rack" => "b"}, 1)
|
64
|
-
assert_read_pool(:secondary,
|
65
|
-
{:db => "main", :rack => "b"}, 1)
|
66
|
-
assert_read_pool(:secondary,
|
67
|
-
{"db" => "main", :rack => "b"}, 1)
|
68
|
-
|
69
|
-
# Test secondary_preferred
|
70
|
-
assert_read_pool(:secondary_preferred,
|
71
|
-
{"dc" => "ny"}, 1)
|
72
|
-
assert_read_pool(:secondary_preferred,
|
73
|
-
{"dc" => "sf"}, 2)
|
74
|
-
assert_read_pool(:secondary_preferred,
|
75
|
-
{"dc" => "china"}, 0)
|
76
|
-
|
77
|
-
# Test secondary_preferred with no matching member
|
78
|
-
assert_read_pool(:secondary_preferred,
|
79
|
-
{"dc" => "bad"}, 0)
|
80
|
-
assert_read_pool(:secondary_preferred,
|
81
|
-
{"db" => "main", "dc" => "china"}, 0)
|
82
|
-
assert_read_pool(:secondary_preferred,
|
83
|
-
{"db" => "ny", "rack" => "a"}, 0)
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_tag_sets
|
87
|
-
return true if @rs.version < "2.1"
|
88
|
-
|
89
|
-
# Test primary_preferred overrides any tags when primary is available
|
90
|
-
assert_read_pool(:primary_preferred, [
|
91
|
-
{"dc" => "sf"}
|
92
|
-
], 0)
|
93
|
-
|
94
|
-
# Test first tag_set takes priority over the second
|
95
|
-
assert_read_pool(:secondary, [
|
96
|
-
{"dc" => "sf"},
|
97
|
-
{"dc" => "ny"}
|
98
|
-
], 2)
|
99
|
-
assert_read_pool(:secondary, [
|
100
|
-
{"dc" => "ny"},
|
101
|
-
{"dc" => "sf"}
|
102
|
-
], 1)
|
103
|
-
assert_read_pool(:secondary_preferred, [
|
104
|
-
{"dc" => "sf"},
|
105
|
-
{"dc" => "ny"}
|
106
|
-
], 2)
|
107
|
-
assert_read_pool(:secondary_preferred, [
|
108
|
-
{"dc" => "ny"},
|
109
|
-
{"dc" => "sf"}
|
110
|
-
], 1)
|
111
|
-
|
112
|
-
# Test tags not matching any member throw an error
|
113
|
-
assert_fail_pool(:secondary, [
|
114
|
-
{"dc" => "ny", "rack" => "a"},
|
115
|
-
{"dc" => "sf", "rack" => "b"},
|
116
|
-
])
|
117
|
-
|
118
|
-
# Test bad tags get skipped over
|
119
|
-
assert_read_pool(:secondary_preferred, [
|
120
|
-
{"bad" => "tag"},
|
121
|
-
{"dc" => "sf"}
|
122
|
-
], 2)
|
123
|
-
|
124
|
-
# Test less selective tags
|
125
|
-
assert_read_pool(:secondary, [
|
126
|
-
{"dc" => "ny", "rack" => "b", "db" => "alt"},
|
127
|
-
{"dc" => "ny", "rack" => "a"},
|
128
|
-
{"dc" => "sf"}
|
129
|
-
], 2)
|
130
|
-
assert_read_pool(:secondary_preferred, [
|
131
|
-
{"dc" => "ny", "rack" => "b", "db" => "alt"},
|
132
|
-
{"dc" => "ny", "rack" => "a"},
|
133
|
-
{"dc" => "sf"}
|
134
|
-
], 2)
|
135
|
-
assert_read_pool(:secondary_preferred, [
|
136
|
-
{"dc" => "ny", "rack" => "a"},
|
137
|
-
{"dc" => "sf", "rack" => "b"},
|
138
|
-
{"db" => "main"}
|
139
|
-
], [1,2])
|
140
|
-
|
141
|
-
# Test secondary preferred gives primary if no tags match
|
142
|
-
assert_read_pool(:secondary_preferred, [
|
143
|
-
{"dc" => "ny", "rack" => "a"},
|
144
|
-
{"dc" => "sf", "rack" => "b"}
|
145
|
-
], 0)
|
146
|
-
assert_read_pool(:secondary_preferred, [
|
147
|
-
{"dc" => "ny", "rack" => "a"},
|
148
|
-
{"dc" => "sf", "rack" => "b"},
|
149
|
-
{"dc" => "ny", "rack" => "b"},
|
150
|
-
], 1)
|
151
|
-
|
152
|
-
# Basic nearest test
|
153
|
-
assert_read_pool(:nearest, [
|
154
|
-
{"dc" => "ny", "rack" => "a"},
|
155
|
-
{"dc" => "sf", "rack" => "b"},
|
156
|
-
{"db" => "main"}
|
157
|
-
], [0,1,2])
|
158
|
-
end
|
159
|
-
|
160
|
-
def test_nearest
|
161
|
-
# Test refresh happens on connection after interval has passed
|
162
|
-
conn = make_connection(
|
163
|
-
:read => :secondary_preferred,
|
164
|
-
:refresh_mode => :sync,
|
165
|
-
:refresh_interval => 1,
|
166
|
-
:secondary_acceptable_latency_ms => 10
|
167
|
-
)
|
168
|
-
pools = conn.manager.pools
|
169
|
-
|
170
|
-
# Connection should select node with 110 ping every time
|
171
|
-
set_pings(pools, [100,110,130])
|
172
|
-
sleep(2)
|
173
|
-
|
174
|
-
assert conn.read_pool == pools[1]
|
175
|
-
|
176
|
-
# Connection should select node with 100 ping every time
|
177
|
-
set_pings(pools, [100,120,100])
|
178
|
-
sleep(2)
|
179
|
-
|
180
|
-
assert conn.read_pool == pools[2]
|
181
|
-
end
|
182
|
-
|
183
|
-
def test_tags_and_nearest
|
184
|
-
return true if @rs.version < "2.1"
|
185
|
-
|
186
|
-
# Test connection's read pool matches tags
|
187
|
-
assert_read_pool(:secondary_preferred, {"dc" => "sf"}, 2, [100,110,130])
|
188
|
-
|
189
|
-
# Test connection's read pool picks near pool (both match tags)
|
190
|
-
assert_read_pool(:secondary_preferred, {"db" => "main"}, 1, [100,110,130])
|
191
|
-
assert_read_pool(:secondary_preferred, {"db" => "main"}, 2, [100,130,110])
|
192
|
-
assert_read_pool(:secondary_preferred, {"db" => "fake"}, 0, [100,130,110])
|
193
|
-
end
|
194
|
-
|
195
|
-
private
|
196
|
-
|
197
|
-
def set_pings(pools, pings)
|
198
|
-
pools.sort! { |a,b| a.port <=> b.port }
|
199
|
-
pools.each_with_index do |pool, index|
|
200
|
-
pool.stubs(:ping_time).returns(pings[index])
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def make_connection(opts = {})
|
205
|
-
ReplSetConnection.new(build_seeds(3), opts)
|
206
|
-
end
|
207
|
-
|
208
|
-
def assert_read_pool(mode=:primary, tags=[], node_nums=[0], pings=[], latency=10)
|
209
|
-
if pings.empty?
|
210
|
-
conn = make_connection({:read => mode, :tag_sets => tags})
|
211
|
-
else
|
212
|
-
conn = make_connection({
|
213
|
-
:read => mode,
|
214
|
-
:tag_sets => tags,
|
215
|
-
:refresh_mode => :sync,
|
216
|
-
:refresh_interval => 1,
|
217
|
-
:secondary_acceptable_latency_ms => latency
|
218
|
-
})
|
219
|
-
|
220
|
-
set_pings(conn.manager.pools, pings)
|
221
|
-
sleep(2)
|
222
|
-
end
|
223
|
-
|
224
|
-
assert conn[MONGO_TEST_DB]['test-sets'].find_one
|
225
|
-
|
226
|
-
target_ports = [*node_nums].collect {|num| @rs.ports[num]}
|
227
|
-
|
228
|
-
assert target_ports.member?(conn.read_pool.port)
|
229
|
-
end
|
230
|
-
|
231
|
-
def assert_fail_pool(mode=:primary, tags={})
|
232
|
-
assert_raise_error ConnectionFailure, "No replica set member available for query " +
|
233
|
-
"with read preference matching mode #{mode} and tags matching #{tags}." do
|
234
|
-
make_connection({:read => mode, :tag_sets => tags}).read_pool
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|