mongo 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. data/{LICENSE.txt → LICENSE} +0 -0
  2. data/README.md +124 -111
  3. data/Rakefile +9 -325
  4. data/VERSION +1 -0
  5. data/bin/mongo_console +4 -4
  6. data/examples/admin.rb +43 -0
  7. data/examples/capped.rb +22 -0
  8. data/examples/cursor.rb +48 -0
  9. data/examples/gridfs.rb +44 -0
  10. data/examples/index_test.rb +126 -0
  11. data/examples/info.rb +31 -0
  12. data/examples/queries.rb +74 -0
  13. data/examples/replica_set.rb +26 -0
  14. data/examples/simple.rb +25 -0
  15. data/examples/strict.rb +35 -0
  16. data/examples/types.rb +36 -0
  17. data/{test/load → examples/web}/thin/load.rb +3 -1
  18. data/{test/load → examples/web}/unicorn/load.rb +5 -3
  19. data/lib/mongo.rb +8 -10
  20. data/lib/mongo/collection.rb +134 -114
  21. data/lib/mongo/cursor.rb +21 -14
  22. data/lib/mongo/db.rb +30 -28
  23. data/lib/mongo/exceptions.rb +1 -1
  24. data/lib/mongo/gridfs/grid.rb +8 -7
  25. data/lib/mongo/gridfs/grid_ext.rb +1 -1
  26. data/lib/mongo/gridfs/grid_file_system.rb +6 -5
  27. data/lib/mongo/gridfs/grid_io.rb +22 -19
  28. data/lib/mongo/legacy.rb +82 -0
  29. data/lib/mongo/{connection.rb → mongo_client.rb} +82 -61
  30. data/lib/mongo/{repl_set_connection.rb → mongo_replica_set_client.rb} +54 -39
  31. data/lib/mongo/{sharded_connection.rb → mongo_sharded_client.rb} +9 -9
  32. data/lib/mongo/networking.rb +25 -20
  33. data/lib/mongo/util/conversions.rb +1 -1
  34. data/lib/mongo/util/core_ext.rb +1 -1
  35. data/lib/mongo/util/logging.rb +20 -4
  36. data/lib/mongo/util/node.rb +16 -16
  37. data/lib/mongo/util/pool.rb +56 -27
  38. data/lib/mongo/util/pool_manager.rb +28 -27
  39. data/lib/mongo/util/server_version.rb +1 -1
  40. data/lib/mongo/util/sharding_pool_manager.rb +8 -8
  41. data/lib/mongo/util/ssl_socket.rb +1 -5
  42. data/lib/mongo/util/support.rb +24 -8
  43. data/lib/mongo/util/tcp_socket.rb +0 -4
  44. data/lib/mongo/util/uri_parser.rb +54 -38
  45. data/lib/mongo/util/write_concern.rb +67 -0
  46. data/mongo.gemspec +21 -32
  47. data/test/auxillary/{1.4_features.rb → 1.4_feature_test.rb} +4 -5
  48. data/test/auxillary/authentication_test.rb +18 -20
  49. data/test/auxillary/autoreconnect_test.rb +3 -5
  50. data/test/auxillary/fork_test.rb +5 -7
  51. data/test/auxillary/repl_set_auth_test.rb +13 -15
  52. data/test/auxillary/slave_connection_test.rb +8 -7
  53. data/test/auxillary/threaded_authentication_test.rb +15 -17
  54. data/test/bson/binary_test.rb +1 -1
  55. data/test/bson/bson_test.rb +60 -36
  56. data/test/bson/byte_buffer_test.rb +1 -1
  57. data/test/bson/hash_with_indifferent_access_test.rb +2 -2
  58. data/test/bson/json_test.rb +1 -2
  59. data/test/bson/object_id_test.rb +1 -2
  60. data/test/bson/ordered_hash_test.rb +1 -1
  61. data/test/bson/timestamp_test.rb +1 -1
  62. data/test/{collection_test.rb → functional/collection_test.rb} +57 -57
  63. data/test/{connection_test.rb → functional/connection_test.rb} +75 -89
  64. data/test/{conversions_test.rb → functional/conversions_test.rb} +1 -1
  65. data/test/{cursor_fail_test.rb → functional/cursor_fail_test.rb} +3 -29
  66. data/test/{cursor_message_test.rb → functional/cursor_message_test.rb} +1 -1
  67. data/test/{cursor_test.rb → functional/cursor_test.rb} +5 -1
  68. data/test/{db_api_test.rb → functional/db_api_test.rb} +8 -9
  69. data/test/{db_connection_test.rb → functional/db_connection_test.rb} +3 -5
  70. data/test/{db_test.rb → functional/db_test.rb} +13 -13
  71. data/test/{grid_file_system_test.rb → functional/grid_file_system_test.rb} +2 -2
  72. data/test/{grid_io_test.rb → functional/grid_io_test.rb} +6 -6
  73. data/test/{grid_test.rb → functional/grid_test.rb} +4 -10
  74. data/test/{pool_test.rb → functional/pool_test.rb} +1 -1
  75. data/test/functional/safe_test.rb +84 -0
  76. data/test/{support_test.rb → functional/support_test.rb} +1 -1
  77. data/test/{threading_test.rb → functional/threading_test.rb} +9 -9
  78. data/test/{timeout_test.rb → functional/timeout_test.rb} +1 -1
  79. data/test/{uri_test.rb → functional/uri_test.rb} +1 -1
  80. data/test/functional/write_concern_test.rb +104 -0
  81. data/test/replica_set/basic_test.rb +139 -0
  82. data/test/replica_set/client_test.rb +255 -0
  83. data/test/replica_set/complex_connect_test.rb +62 -0
  84. data/test/replica_set/connection_test.rb +255 -0
  85. data/test/{replica_sets → replica_set}/count_test.rb +17 -14
  86. data/test/replica_set/cursor_test.rb +75 -0
  87. data/test/{replica_sets → replica_set}/insert_test.rb +19 -16
  88. data/test/replica_set/query_test.rb +64 -0
  89. data/test/replica_set/refresh_test.rb +153 -0
  90. data/test/{replica_sets → replica_set}/replication_ack_test.rb +21 -17
  91. data/test/sharded_cluster/basic_test.rb +31 -50
  92. data/test/support/hash_with_indifferent_access.rb +1 -1
  93. data/test/test_helper.rb +56 -9
  94. data/test/threading/threading_with_large_pool_test.rb +8 -8
  95. data/test/tools/mongo_config.rb +270 -58
  96. data/test/tools/mongo_config_test.rb +146 -0
  97. data/test/unit/client_test.rb +230 -0
  98. data/test/unit/collection_test.rb +45 -32
  99. data/test/unit/connection_test.rb +82 -74
  100. data/test/unit/cursor_test.rb +14 -6
  101. data/test/unit/db_test.rb +8 -8
  102. data/test/unit/grid_test.rb +11 -11
  103. data/test/unit/node_test.rb +24 -24
  104. data/test/unit/pool_manager_test.rb +13 -13
  105. data/test/unit/pool_test.rb +1 -1
  106. data/test/unit/read_test.rb +21 -26
  107. data/test/unit/safe_test.rb +52 -33
  108. data/test/unit/util_test.rb +55 -0
  109. data/test/unit/write_concern_test.rb +161 -0
  110. metadata +158 -171
  111. data/docs/CREDITS.md +0 -123
  112. data/docs/FAQ.md +0 -116
  113. data/docs/GRID_FS.md +0 -158
  114. data/docs/HISTORY.md +0 -392
  115. data/docs/READ_PREFERENCE.md +0 -99
  116. data/docs/RELEASES.md +0 -54
  117. data/docs/REPLICA_SETS.md +0 -113
  118. data/docs/TAILABLE_CURSORS.md +0 -51
  119. data/docs/TUTORIAL.md +0 -356
  120. data/docs/WRITE_CONCERN.md +0 -31
  121. data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
  122. data/lib/mongo/version.rb +0 -3
  123. data/test/bson/test_helper.rb +0 -30
  124. data/test/replica_sets/basic_test.rb +0 -119
  125. data/test/replica_sets/complex_connect_test.rb +0 -57
  126. data/test/replica_sets/complex_read_preference_test.rb +0 -237
  127. data/test/replica_sets/connect_test.rb +0 -156
  128. data/test/replica_sets/cursor_test.rb +0 -70
  129. data/test/replica_sets/pooled_insert_test.rb +0 -57
  130. data/test/replica_sets/query_test.rb +0 -50
  131. data/test/replica_sets/read_preference_test.rb +0 -234
  132. data/test/replica_sets/refresh_test.rb +0 -156
  133. data/test/replica_sets/refresh_with_threads_test.rb +0 -60
  134. data/test/replica_sets/rs_test_helper.rb +0 -39
  135. data/test/safe_test.rb +0 -68
  136. data/test/sharded_cluster/mongo_config_test.rb +0 -126
  137. data/test/sharded_cluster/sc_test_helper.rb +0 -39
  138. data/test/tools/repl_set_manager.rb +0 -418
@@ -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
@@ -1,3 +0,0 @@
1
- module Mongo
2
- VERSION = "1.7.1"
3
- end
@@ -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