mongo 2.10.5 → 2.11.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CONTRIBUTING.md +1 -1
- data/lib/mongo.rb +2 -0
- data/lib/mongo/address.rb +4 -0
- data/lib/mongo/address/validator.rb +99 -0
- data/lib/mongo/auth.rb +7 -2
- data/lib/mongo/auth/user.rb +1 -7
- data/lib/mongo/background_thread.rb +135 -0
- data/lib/mongo/bulk_write/transformable.rb +3 -3
- data/lib/mongo/client.rb +74 -16
- data/lib/mongo/cluster.rb +193 -41
- data/lib/mongo/cluster/periodic_executor.rb +31 -43
- data/lib/mongo/cluster/sdam_flow.rb +26 -3
- data/lib/mongo/cluster/srv_monitor.rb +127 -0
- data/lib/mongo/collection/view/readable.rb +3 -5
- data/lib/mongo/collection/view/writable.rb +3 -3
- data/lib/mongo/cursor/builder/get_more_command.rb +1 -4
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +5 -23
- data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +5 -24
- data/lib/mongo/error.rb +1 -0
- data/lib/mongo/error/auth_error.rb +1 -1
- data/lib/mongo/error/connection_check_out_timeout.rb +7 -8
- data/lib/mongo/error/invalid_address.rb +24 -0
- data/lib/mongo/error/notable.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +3 -3
- data/lib/mongo/error/pool_closed_error.rb +11 -4
- data/lib/mongo/event.rb +1 -1
- data/lib/mongo/grid/file.rb +0 -5
- data/lib/mongo/grid/file/chunk.rb +0 -2
- data/lib/mongo/grid/fs_bucket.rb +13 -15
- data/lib/mongo/grid/stream/write.rb +3 -9
- data/lib/mongo/loggable.rb +5 -1
- data/lib/mongo/monitoring.rb +1 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +7 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +11 -3
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +12 -3
- data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +62 -0
- data/lib/mongo/operation/shared/executable.rb +5 -10
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -5
- data/lib/mongo/protocol/get_more.rb +1 -2
- data/lib/mongo/protocol/kill_cursors.rb +13 -6
- data/lib/mongo/protocol/serializers.rb +4 -20
- data/lib/mongo/retryable.rb +9 -34
- data/lib/mongo/semaphore.rb +1 -1
- data/lib/mongo/server.rb +113 -42
- data/lib/mongo/server/connection.rb +12 -5
- data/lib/mongo/server/connection_pool.rb +250 -40
- data/lib/mongo/server/connection_pool/populator.rb +58 -0
- data/lib/mongo/server/description.rb +9 -2
- data/lib/mongo/server/monitor.rb +68 -93
- data/lib/mongo/server/monitor/connection.rb +2 -0
- data/lib/mongo/server_selector/selectable.rb +13 -5
- data/lib/mongo/session.rb +0 -13
- data/lib/mongo/srv.rb +17 -0
- data/lib/mongo/srv/monitor.rb +96 -0
- data/lib/mongo/srv/resolver.rb +130 -0
- data/lib/mongo/srv/result.rb +126 -0
- data/lib/mongo/srv/warning_result.rb +35 -0
- data/lib/mongo/uri.rb +45 -55
- data/lib/mongo/uri/srv_protocol.rb +89 -42
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +3 -4
- data/spec/README.md +6 -1
- data/spec/enterprise_auth/kerberos_spec.rb +7 -6
- data/spec/integration/change_stream_examples_spec.rb +0 -4
- data/spec/integration/client_construction_spec.rb +14 -2
- data/spec/integration/connect_single_rs_name_spec.rb +2 -2
- data/spec/integration/connection_pool_populator_spec.rb +296 -0
- data/spec/integration/connection_spec.rb +31 -22
- data/spec/integration/cursor_reaping_spec.rb +1 -2
- data/spec/integration/docs_examples_spec.rb +0 -4
- data/spec/integration/heartbeat_events_spec.rb +17 -15
- data/spec/integration/reconnect_spec.rb +144 -1
- data/spec/integration/retryable_writes_errors_spec.rb +0 -4
- data/spec/integration/retryable_writes_spec.rb +36 -36
- data/spec/integration/sdam_error_handling_spec.rb +31 -25
- data/spec/integration/sdam_events_spec.rb +2 -6
- data/spec/integration/server_monitor_spec.rb +28 -0
- data/spec/integration/server_selector_spec.rb +7 -5
- data/spec/integration/srv_monitoring_spec.rb +360 -0
- data/spec/integration/step_down_spec.rb +4 -6
- data/spec/lite_spec_helper.rb +22 -0
- data/spec/mongo/address/validator_spec.rb +51 -0
- data/spec/mongo/auth/cr_spec.rb +1 -29
- data/spec/mongo/auth/ldap_spec.rb +1 -29
- data/spec/mongo/auth/scram/conversation_spec.rb +0 -2
- data/spec/mongo/auth/scram/negotiation_spec.rb +1 -1
- data/spec/mongo/auth/scram_spec.rb +1 -29
- data/spec/mongo/auth/user/view_spec.rb +1 -36
- data/spec/mongo/auth/user_spec.rb +0 -12
- data/spec/mongo/auth/x509_spec.rb +1 -29
- data/spec/mongo/bulk_write_spec.rb +2 -2
- data/spec/mongo/client_construction_spec.rb +56 -15
- data/spec/mongo/client_spec.rb +31 -27
- data/spec/mongo/cluster/periodic_executor_spec.rb +16 -0
- data/spec/mongo/cluster/srv_monitor_spec.rb +214 -0
- data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -11
- data/spec/mongo/cluster/topology/sharded_spec.rb +12 -9
- data/spec/mongo/cluster/topology/single_spec.rb +20 -11
- data/spec/mongo/cluster_spec.rb +45 -29
- data/spec/mongo/collection/view/map_reduce_spec.rb +14 -9
- data/spec/mongo/collection/view/readable_spec.rb +0 -16
- data/spec/mongo/collection_spec.rb +0 -44
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +2 -4
- data/spec/mongo/cursor/builder/op_get_more_spec.rb +2 -4
- data/spec/mongo/cursor_spec.rb +27 -7
- data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +10 -3
- data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +10 -3
- data/spec/mongo/operation/delete/op_msg_spec.rb +17 -8
- data/spec/mongo/operation/insert/op_msg_spec.rb +50 -35
- data/spec/mongo/operation/update/op_msg_spec.rb +14 -7
- data/spec/mongo/retryable_spec.rb +52 -31
- data/spec/mongo/server/app_metadata_spec.rb +0 -8
- data/spec/mongo/server/connection_auth_spec.rb +5 -2
- data/spec/mongo/server/connection_pool/populator_spec.rb +101 -0
- data/spec/mongo/server/connection_pool_spec.rb +256 -107
- data/spec/mongo/server/connection_spec.rb +22 -33
- data/spec/mongo/server/description_spec.rb +42 -4
- data/spec/mongo/server/monitor/connection_spec.rb +22 -11
- data/spec/mongo/server/monitor_spec.rb +66 -107
- data/spec/mongo/server_spec.rb +82 -60
- data/spec/mongo/session/session_pool_spec.rb +1 -5
- data/spec/mongo/session_spec.rb +0 -4
- data/spec/mongo/socket/ssl_spec.rb +2 -2
- data/spec/mongo/srv/monitor_spec.rb +211 -0
- data/spec/mongo/srv/result_spec.rb +54 -0
- data/spec/mongo/uri/srv_protocol_spec.rb +30 -15
- data/spec/mongo/uri_spec.rb +125 -4
- data/spec/spec_helper.rb +6 -0
- data/spec/spec_tests/auth_spec.rb +39 -0
- data/spec/spec_tests/cmap_spec.rb +55 -8
- data/spec/spec_tests/connection_string_spec.rb +6 -31
- data/spec/spec_tests/data/auth/connection-string.yml +297 -0
- data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +4 -1
- data/spec/spec_tests/data/cmap/pool-create-with-options.yml +1 -0
- data/spec/spec_tests/data/command_monitoring/insertMany.yml +1 -1
- data/spec/spec_tests/data/connection_string/invalid-uris.yml +20 -0
- data/spec/spec_tests/data/connection_string/valid-auth.yml +16 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +26 -30
- data/spec/spec_tests/data/transactions/abort.yml +3 -3
- data/spec/spec_tests/data/transactions/error-labels.yml +3 -3
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +3 -3
- data/spec/spec_tests/data/uri_options/auth-options.yml +1 -1
- data/spec/spec_tests/max_staleness_spec.rb +7 -2
- data/spec/spec_tests/retryable_reads_spec.rb +0 -31
- data/spec/spec_tests/sdam_monitoring_spec.rb +12 -12
- data/spec/spec_tests/sdam_spec.rb +4 -7
- data/spec/spec_tests/server_selection_spec.rb +6 -2
- data/spec/spec_tests/transactions_spec.rb +0 -2
- data/spec/spec_tests/uri_options_spec.rb +4 -2
- data/spec/stress/connection_pool_stress_spec.rb +203 -0
- data/spec/stress/connection_pool_timing_spec.rb +181 -0
- data/spec/support/auth.rb +113 -0
- data/spec/support/background_thread_registry.rb +63 -0
- data/spec/support/client_registry.rb +11 -2
- data/spec/support/cluster_config.rb +65 -46
- data/spec/support/cluster_tools.rb +2 -2
- data/spec/support/cmap.rb +13 -14
- data/spec/support/cmap/verifier.rb +4 -5
- data/spec/support/command_monitoring.rb +0 -5
- data/spec/support/common_shortcuts.rb +101 -1
- data/spec/support/constraints.rb +25 -0
- data/spec/support/dns.rb +13 -0
- data/spec/support/event_subscriber.rb +0 -7
- data/spec/support/json_ext_formatter.rb +5 -1
- data/spec/support/lite_constraints.rb +22 -6
- data/spec/support/local_resource_registry.rb +34 -0
- data/spec/support/sdam_monitoring.rb +115 -0
- data/spec/support/spec_config.rb +20 -6
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +1 -1
- data/spec/support/transactions/test.rb +1 -1
- data/spec/support/utils.rb +1 -16
- metadata +685 -659
- metadata.gz.sig +0 -0
- data/lib/mongo/event/description_changed.rb +0 -52
- data/spec/integration/bson_symbol_spec.rb +0 -34
- data/spec/integration/crud_spec.rb +0 -45
- data/spec/integration/get_more_spec.rb +0 -32
- data/spec/integration/grid_fs_bucket_spec.rb +0 -48
- data/spec/integration/retryable_errors_spec.rb +0 -265
- data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +0 -98
- data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
- data/spec/runners/sdam/verifier.rb +0 -88
@@ -22,10 +22,6 @@ describe Mongo::Server::AppMetadata do
|
|
22
22
|
client.cluster
|
23
23
|
end
|
24
24
|
|
25
|
-
after do
|
26
|
-
client.close(true)
|
27
|
-
end
|
28
|
-
|
29
25
|
it 'sets the app name' do
|
30
26
|
expect(app_metadata.send(:full_client_document)[:application][:name]).to eq('app_metadata_test')
|
31
27
|
end
|
@@ -40,10 +36,6 @@ describe Mongo::Server::AppMetadata do
|
|
40
36
|
client.cluster
|
41
37
|
end
|
42
38
|
|
43
|
-
after do
|
44
|
-
client.close(true)
|
45
|
-
end
|
46
|
-
|
47
39
|
it 'raises an error' do
|
48
40
|
expect {
|
49
41
|
app_metadata.send(:validate!)
|
@@ -25,6 +25,7 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
25
25
|
allow(cl).to receive(:options).and_return({})
|
26
26
|
allow(cl).to receive(:cluster_time).and_return(nil)
|
27
27
|
allow(cl).to receive(:update_cluster_time)
|
28
|
+
allow(cl).to receive(:run_sdam_flow)
|
28
29
|
pool = double('pool')
|
29
30
|
allow(pool).to receive(:disconnect!)
|
30
31
|
allow(cl).to receive(:pool).and_return(pool)
|
@@ -34,8 +35,10 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
34
35
|
declare_topology_double
|
35
36
|
|
36
37
|
let(:server) do
|
37
|
-
|
38
|
-
|
38
|
+
register_server(
|
39
|
+
Mongo::Server.new(address, cluster, monitoring, listeners,
|
40
|
+
SpecConfig.instance.test_options.merge(monitoring_io: false))
|
41
|
+
)
|
39
42
|
end
|
40
43
|
|
41
44
|
before(:all) do
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Server::Populator do
|
4
|
+
let(:options) { {} }
|
5
|
+
|
6
|
+
let(:client) do
|
7
|
+
authorized_client.with(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:server) do
|
11
|
+
client.cluster.next_primary
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:pool) do
|
15
|
+
server.pool
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:populator) do
|
19
|
+
register_background_thread_object(
|
20
|
+
described_class.new(pool, pool.options)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
# We create our own populator to test; disable pool's background populator
|
26
|
+
# and clear the pool, so ours can run
|
27
|
+
pool.stop_populator
|
28
|
+
pool.clear
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#log_warn' do
|
32
|
+
it 'works' do
|
33
|
+
expect do
|
34
|
+
populator.log_warn('test warning')
|
35
|
+
end.not_to raise_error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
describe '#run!' do
|
41
|
+
context 'when the min_pool_size is zero' do
|
42
|
+
let(:options) { {min_pool_size: 0} }
|
43
|
+
|
44
|
+
it 'calls populate on pool once' do
|
45
|
+
expect(pool).to receive(:populate).once.and_call_original
|
46
|
+
populator.run!
|
47
|
+
sleep 1
|
48
|
+
expect(populator.running?).to be true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when the min_pool_size is greater than zero' do
|
53
|
+
let(:options) { {min_pool_size: 2, max_pool_size: 3} }
|
54
|
+
|
55
|
+
it 'calls populate on the pool multiple times' do
|
56
|
+
expect(pool).to receive(:populate).at_least(:once).and_call_original
|
57
|
+
populator.run!
|
58
|
+
sleep 1
|
59
|
+
expect(populator.running?).to be true
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'populates the pool up to min_size' do
|
63
|
+
populator.run!
|
64
|
+
sleep 1
|
65
|
+
expect(pool.size).to eq 2
|
66
|
+
expect(populator.running?).to be true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when populate raises a non socket related error' do
|
71
|
+
it 'does not terminate the thread' do
|
72
|
+
expect(pool).to receive(:populate).once.and_raise(Mongo::Auth::InvalidMechanism.new(""))
|
73
|
+
populator.run!
|
74
|
+
sleep 0.5
|
75
|
+
expect(populator.running?).to be true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when populate raises a socket related error' do
|
80
|
+
it 'does not terminate the thread' do
|
81
|
+
expect(pool).to receive(:populate).once.and_raise(Mongo::Error::SocketError)
|
82
|
+
populator.run!
|
83
|
+
sleep 0.5
|
84
|
+
expect(populator.running?).to be true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#stop' do
|
90
|
+
it 'stops calling populate on pool and terminates the thread' do
|
91
|
+
populator.run!
|
92
|
+
|
93
|
+
# let populator do work and wait on semaphore
|
94
|
+
sleep 0.5
|
95
|
+
|
96
|
+
expect(pool).not_to receive(:populate)
|
97
|
+
populator.stop!
|
98
|
+
expect(populator.running?).to be false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -2,10 +2,12 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongo::Server::ConnectionPool do
|
4
4
|
|
5
|
-
let(:options) { {
|
5
|
+
let(:options) { {} }
|
6
6
|
|
7
7
|
let(:server_options) do
|
8
|
-
SpecConfig.instance.
|
8
|
+
SpecConfig.instance.ssl_options.merge(SpecConfig.instance.compressor_options)
|
9
|
+
.merge(SpecConfig.instance.retry_writes_options).merge(SpecConfig.instance.auth_options)
|
10
|
+
.merge(options)
|
9
11
|
end
|
10
12
|
|
11
13
|
let(:address) do
|
@@ -28,28 +30,39 @@ describe Mongo::Server::ConnectionPool do
|
|
28
30
|
allow(cl).to receive(:app_metadata).and_return(app_metadata)
|
29
31
|
allow(cl).to receive(:options).and_return({})
|
30
32
|
allow(cl).to receive(:update_cluster_time)
|
33
|
+
allow(cl).to receive(:cluster_time).and_return(nil)
|
34
|
+
allow(cl).to receive(:run_sdam_flow)
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
34
38
|
let(:server) do
|
35
|
-
|
39
|
+
register_server(
|
40
|
+
Mongo::Server.new(address, cluster, monitoring, listeners,
|
41
|
+
{monitoring_io: false}.update(server_options)
|
42
|
+
).tap do |server|
|
43
|
+
allow(server).to receive(:description).and_return(ClusterConfig.instance.primary_description)
|
44
|
+
end
|
45
|
+
)
|
36
46
|
end
|
37
47
|
|
38
48
|
let(:pool) do
|
39
|
-
described_class.new(server)
|
49
|
+
register_pool(described_class.new(server, server_options))
|
40
50
|
end
|
41
51
|
|
42
52
|
describe '#initialize' do
|
43
53
|
|
44
54
|
context 'when a min size is provided' do
|
45
|
-
|
46
|
-
|
47
|
-
described_class.new(server, :min_pool_size => 2)
|
55
|
+
let (:options) do
|
56
|
+
{ min_pool_size: 2 }
|
48
57
|
end
|
49
58
|
|
50
|
-
it 'creates the pool with
|
51
|
-
|
52
|
-
|
59
|
+
it 'creates the pool with min size connections' do
|
60
|
+
# Allow background thread to populate pool
|
61
|
+
pool
|
62
|
+
sleep 1
|
63
|
+
|
64
|
+
expect(pool.size).to eq(2)
|
65
|
+
expect(pool.available_count).to eq(2)
|
53
66
|
end
|
54
67
|
|
55
68
|
it 'does not use the same objects in the pool' do
|
@@ -58,9 +71,8 @@ describe Mongo::Server::ConnectionPool do
|
|
58
71
|
end
|
59
72
|
|
60
73
|
context 'when min size exceeds default max size' do
|
61
|
-
|
62
|
-
|
63
|
-
described_class.new(server, :min_pool_size => 10)
|
74
|
+
let (:options) do
|
75
|
+
{ min_pool_size: 10 }
|
64
76
|
end
|
65
77
|
|
66
78
|
it 'sets max size to equal provided min size' do
|
@@ -70,10 +82,6 @@ describe Mongo::Server::ConnectionPool do
|
|
70
82
|
|
71
83
|
context 'when no min size is provided' do
|
72
84
|
|
73
|
-
let(:pool) do
|
74
|
-
described_class.new(server)
|
75
|
-
end
|
76
|
-
|
77
85
|
it 'creates the pool with no connections' do
|
78
86
|
expect(pool.size).to eq(0)
|
79
87
|
expect(pool.available_count).to eq(0)
|
@@ -81,9 +89,8 @@ describe Mongo::Server::ConnectionPool do
|
|
81
89
|
end
|
82
90
|
|
83
91
|
context 'sizes given as min_size and max_size' do
|
84
|
-
|
85
|
-
|
86
|
-
described_class.new(server, min_size: 3, max_size: 7)
|
92
|
+
let (:options) do
|
93
|
+
{ min_size: 3, max_size: 7 }
|
87
94
|
end
|
88
95
|
|
89
96
|
it 'sets sizes correctly' do
|
@@ -93,9 +100,8 @@ describe Mongo::Server::ConnectionPool do
|
|
93
100
|
end
|
94
101
|
|
95
102
|
context 'sizes given as min_pool_size and max_pool_size' do
|
96
|
-
|
97
|
-
|
98
|
-
described_class.new(server, min_pool_size: 3, max_pool_size: 7)
|
103
|
+
let (:options) do
|
104
|
+
{ min_pool_size: 3, max_pool_size: 7 }
|
99
105
|
end
|
100
106
|
|
101
107
|
it 'sets sizes correctly' do
|
@@ -105,9 +111,8 @@ describe Mongo::Server::ConnectionPool do
|
|
105
111
|
end
|
106
112
|
|
107
113
|
context 'timeout given as wait_timeout' do
|
108
|
-
|
109
|
-
|
110
|
-
described_class.new(server, wait_timeout: 4)
|
114
|
+
let (:options) do
|
115
|
+
{ wait_timeout: 4 }
|
111
116
|
end
|
112
117
|
|
113
118
|
it 'sets wait timeout correctly' do
|
@@ -116,9 +121,8 @@ describe Mongo::Server::ConnectionPool do
|
|
116
121
|
end
|
117
122
|
|
118
123
|
context 'timeout given as wait_queue_timeout' do
|
119
|
-
|
120
|
-
|
121
|
-
described_class.new(server, wait_queue_timeout: 4)
|
124
|
+
let (:options) do
|
125
|
+
{ wait_queue_timeout: 4 }
|
122
126
|
end
|
123
127
|
|
124
128
|
it 'sets wait timeout correctly' do
|
@@ -128,11 +132,9 @@ describe Mongo::Server::ConnectionPool do
|
|
128
132
|
end
|
129
133
|
|
130
134
|
describe '#max_size' do
|
131
|
-
|
132
135
|
context 'when a max pool size option is provided' do
|
133
|
-
|
134
|
-
|
135
|
-
described_class.new(server, :max_pool_size => 3)
|
136
|
+
let (:options) do
|
137
|
+
{ max_pool_size: 3 }
|
136
138
|
end
|
137
139
|
|
138
140
|
it 'returns the max size' do
|
@@ -141,7 +143,6 @@ describe Mongo::Server::ConnectionPool do
|
|
141
143
|
end
|
142
144
|
|
143
145
|
context 'when no pool size option is provided' do
|
144
|
-
|
145
146
|
it 'returns the default size' do
|
146
147
|
expect(pool.max_size).to eq(5)
|
147
148
|
end
|
@@ -159,11 +160,9 @@ describe Mongo::Server::ConnectionPool do
|
|
159
160
|
end
|
160
161
|
|
161
162
|
describe '#wait_timeout' do
|
162
|
-
|
163
163
|
context 'when the wait timeout option is provided' do
|
164
|
-
|
165
|
-
|
166
|
-
described_class.new(server, :wait_queue_timeout => 3)
|
164
|
+
let (:options) do
|
165
|
+
{ wait_queue_timeout: 3 }
|
167
166
|
end
|
168
167
|
|
169
168
|
it 'returns the wait timeout' do
|
@@ -172,9 +171,8 @@ describe Mongo::Server::ConnectionPool do
|
|
172
171
|
end
|
173
172
|
|
174
173
|
context 'when the wait timeout option is not provided' do
|
175
|
-
|
176
174
|
it 'returns the default wait timeout' do
|
177
|
-
expect(pool.wait_timeout).to eq(
|
175
|
+
expect(pool.wait_timeout).to eq(10)
|
178
176
|
end
|
179
177
|
end
|
180
178
|
end
|
@@ -280,17 +278,17 @@ describe Mongo::Server::ConnectionPool do
|
|
280
278
|
end
|
281
279
|
|
282
280
|
describe '#check_in' do
|
283
|
-
|
284
281
|
let!(:pool) do
|
285
282
|
server.pool
|
286
283
|
end
|
287
284
|
|
288
285
|
after do
|
289
|
-
expect(server).to receive(:pool).and_return(pool)
|
290
286
|
server.disconnect!
|
291
287
|
end
|
292
288
|
|
293
|
-
let(:options)
|
289
|
+
let(:options) do
|
290
|
+
{ max_pool_size: 2 }
|
291
|
+
end
|
294
292
|
|
295
293
|
let(:connection) do
|
296
294
|
pool.check_out
|
@@ -348,7 +346,7 @@ describe Mongo::Server::ConnectionPool do
|
|
348
346
|
end
|
349
347
|
|
350
348
|
before do
|
351
|
-
expect(connection.generation < pool.generation
|
349
|
+
expect(connection.generation).to be < pool.generation
|
352
350
|
end
|
353
351
|
|
354
352
|
it_behaves_like 'does not add connection to pool'
|
@@ -370,8 +368,6 @@ describe Mongo::Server::ConnectionPool do
|
|
370
368
|
end
|
371
369
|
|
372
370
|
context 'when pool is closed' do
|
373
|
-
let(:connection) { pool.check_out }
|
374
|
-
|
375
371
|
before do
|
376
372
|
connection
|
377
373
|
pool.close
|
@@ -385,10 +381,32 @@ describe Mongo::Server::ConnectionPool do
|
|
385
381
|
expect(pool.instance_variable_get('@available_connections').length).to eq(0)
|
386
382
|
end
|
387
383
|
end
|
384
|
+
|
385
|
+
context 'when connection is checked in twice' do
|
386
|
+
it 'raises an ArgumentError and does not change pool state' do
|
387
|
+
pool.check_in(connection)
|
388
|
+
expect do
|
389
|
+
pool.check_in(connection)
|
390
|
+
end.to raise_error(ArgumentError, /Trying to check in a connection which is not currently checked out by this pool.*/)
|
391
|
+
expect(pool.size).to eq(1)
|
392
|
+
expect(pool.check_out).to eq(connection)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context 'when connection is checked in to a different pool' do
|
397
|
+
it 'raises an ArgumentError and does not change the state of either pool' do
|
398
|
+
pool_other = register_pool(described_class.new(server))
|
399
|
+
|
400
|
+
expect do
|
401
|
+
pool_other.check_in(connection)
|
402
|
+
end.to raise_error(ArgumentError, /Trying to check in a connection which was not checked out by this pool.*/)
|
403
|
+
expect(pool.size).to eq(1)
|
404
|
+
expect(pool_other.size).to eq(0)
|
405
|
+
end
|
406
|
+
end
|
388
407
|
end
|
389
408
|
|
390
409
|
describe '#check_out' do
|
391
|
-
|
392
410
|
let!(:pool) do
|
393
411
|
server.pool
|
394
412
|
end
|
@@ -421,7 +439,7 @@ describe Mongo::Server::ConnectionPool do
|
|
421
439
|
|
422
440
|
context 'when there is an available connection which is stale' do
|
423
441
|
let(:options) do
|
424
|
-
{max_pool_size: 2, max_idle_time: 0.1}
|
442
|
+
{ max_pool_size: 2, max_idle_time: 0.1 }
|
425
443
|
end
|
426
444
|
|
427
445
|
let(:connection) do
|
@@ -436,10 +454,6 @@ describe Mongo::Server::ConnectionPool do
|
|
436
454
|
pool.check_in(connection)
|
437
455
|
end
|
438
456
|
|
439
|
-
after do
|
440
|
-
pool.close(force: true)
|
441
|
-
end
|
442
|
-
|
443
457
|
it 'closes stale connection and creates a new one' do
|
444
458
|
expect(connection).to receive(:disconnect!)
|
445
459
|
expect(Mongo::Server::Connection).to receive(:new).and_call_original
|
@@ -450,7 +464,7 @@ describe Mongo::Server::ConnectionPool do
|
|
450
464
|
context 'when there are no available connections' do
|
451
465
|
|
452
466
|
let(:options) do
|
453
|
-
{max_pool_size: 1}
|
467
|
+
{ max_pool_size: 1, min_pool_size: 0 }
|
454
468
|
end
|
455
469
|
|
456
470
|
context 'when the max size is not reached' do
|
@@ -503,12 +517,43 @@ describe Mongo::Server::ConnectionPool do
|
|
503
517
|
end.to raise_error(Mongo::Error::PoolClosedError)
|
504
518
|
end
|
505
519
|
end
|
520
|
+
|
521
|
+
context 'when connection set up throws an error during check out' do
|
522
|
+
let(:client) do
|
523
|
+
authorized_client
|
524
|
+
end
|
525
|
+
|
526
|
+
let(:pool) do
|
527
|
+
client.cluster.next_primary.pool
|
528
|
+
end
|
529
|
+
|
530
|
+
it 'raises an error and emits ConnectionCheckOutFailedEvent' do
|
531
|
+
pool
|
532
|
+
|
533
|
+
subscriber = EventSubscriber.new
|
534
|
+
client.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)
|
535
|
+
|
536
|
+
subscriber.clear_events!
|
537
|
+
expect(Mongo::Auth).to receive(:get).at_least(:once).and_raise(Mongo::Error)
|
538
|
+
expect { pool.check_out }.to raise_error(Mongo::Error)
|
539
|
+
expect(pool.size).to eq(0)
|
540
|
+
|
541
|
+
checkout_failed_events = subscriber.published_events.select do |event|
|
542
|
+
event.is_a?(Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed)
|
543
|
+
end
|
544
|
+
expect(checkout_failed_events.size).to eq(1)
|
545
|
+
expect(checkout_failed_events.first.reason).to be(:connection_error)
|
546
|
+
end
|
547
|
+
end
|
506
548
|
end
|
507
549
|
|
508
550
|
describe '#disconnect!' do
|
509
|
-
|
510
551
|
def create_pool(min_pool_size)
|
511
|
-
|
552
|
+
opts = SpecConfig.instance.test_options.merge(max_pool_size: 3, min_pool_size: min_pool_size)
|
553
|
+
described_class.new(server, opts).tap do |pool|
|
554
|
+
# kill background thread to test disconnect behavior
|
555
|
+
pool.stop_populator
|
556
|
+
expect(pool.instance_variable_get('@populator').running?).to be false
|
512
557
|
# make pool be of size 2 so that it has enqueued connections
|
513
558
|
# when told to disconnect
|
514
559
|
c1 = pool.check_out
|
@@ -546,7 +591,7 @@ describe Mongo::Server::ConnectionPool do
|
|
546
591
|
|
547
592
|
context 'min size is 0' do
|
548
593
|
let(:pool) do
|
549
|
-
create_pool(0)
|
594
|
+
register_pool(create_pool(0))
|
550
595
|
end
|
551
596
|
|
552
597
|
it_behaves_like 'disconnects and removes all connections in the pool and bumps generation'
|
@@ -554,7 +599,7 @@ describe Mongo::Server::ConnectionPool do
|
|
554
599
|
|
555
600
|
context 'min size is not 0' do
|
556
601
|
let(:pool) do
|
557
|
-
create_pool(1)
|
602
|
+
register_pool(create_pool(1))
|
558
603
|
end
|
559
604
|
|
560
605
|
it_behaves_like 'disconnects and removes all connections in the pool and bumps generation'
|
@@ -597,15 +642,17 @@ describe Mongo::Server::ConnectionPool do
|
|
597
642
|
end
|
598
643
|
|
599
644
|
describe '#inspect' do
|
600
|
-
let(:options)
|
645
|
+
let(:options) do
|
646
|
+
{ min_pool_size: 3, max_pool_size: 7, wait_timeout: 9, wait_queue_timeout: 9 }
|
647
|
+
end
|
601
648
|
|
602
649
|
let!(:pool) do
|
603
650
|
server.pool
|
604
651
|
end
|
605
652
|
|
606
653
|
after do
|
607
|
-
expect(server).to receive(:pool).and_return(pool)
|
608
654
|
server.disconnect!
|
655
|
+
pool.close # this will no longer be needed after server disconnect kills bg thread
|
609
656
|
end
|
610
657
|
|
611
658
|
it 'includes the object id' do
|
@@ -625,7 +672,7 @@ describe Mongo::Server::ConnectionPool do
|
|
625
672
|
end
|
626
673
|
|
627
674
|
it 'includes the current size' do
|
628
|
-
expect(pool.inspect).to include('current_size=
|
675
|
+
expect(pool.inspect).to include('current_size=')
|
629
676
|
end
|
630
677
|
|
631
678
|
=begin obsolete
|
@@ -654,7 +701,6 @@ describe Mongo::Server::ConnectionPool do
|
|
654
701
|
end
|
655
702
|
|
656
703
|
describe '#with_connection' do
|
657
|
-
|
658
704
|
let!(:pool) do
|
659
705
|
server.pool
|
660
706
|
end
|
@@ -662,10 +708,11 @@ describe Mongo::Server::ConnectionPool do
|
|
662
708
|
context 'when a connection cannot be checked out' do
|
663
709
|
|
664
710
|
it 'does not add the connection to the pool' do
|
665
|
-
|
666
|
-
|
711
|
+
# fails because with_connection raises the SocketError which is not caught anywhere
|
667
712
|
allow(pool).to receive(:check_out).and_raise(Mongo::Error::SocketError)
|
668
|
-
|
713
|
+
expect do
|
714
|
+
pool.with_connection { |c| c }
|
715
|
+
end.to raise_error(Mongo::Error::SocketError)
|
669
716
|
|
670
717
|
expect(pool.size).to eq(0)
|
671
718
|
end
|
@@ -685,13 +732,12 @@ describe Mongo::Server::ConnectionPool do
|
|
685
732
|
end
|
686
733
|
|
687
734
|
context 'when the connection does not finish authenticating before the thread is killed' do
|
688
|
-
|
689
735
|
let!(:pool) do
|
690
736
|
server.pool
|
691
737
|
end
|
692
738
|
|
693
|
-
let(:
|
694
|
-
{
|
739
|
+
let(:options) do
|
740
|
+
{ min_pool_size:0, max_pool_size: 1 }
|
695
741
|
end
|
696
742
|
|
697
743
|
before do
|
@@ -700,32 +746,23 @@ describe Mongo::Server::ConnectionPool do
|
|
700
746
|
end
|
701
747
|
|
702
748
|
it 'creates a new connection' do
|
703
|
-
invoked = nil
|
704
|
-
|
705
749
|
t = Thread.new do
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
750
|
+
expect {
|
751
|
+
pool.with_connection do |c|
|
752
|
+
expect(c).to receive(:connect!).and_raise(Mongo::Error)
|
753
|
+
c.send(:ensure_connected) { |socket| socket}
|
710
754
|
end
|
711
|
-
|
712
|
-
|
713
|
-
raise 'Should not get here'
|
714
|
-
end
|
715
|
-
pool.with_connection do |c|
|
716
|
-
c.send(:ensure_connected) { |socket| socket }
|
717
|
-
end
|
755
|
+
}.to raise_error(Mongo::Error)
|
756
|
+
expect(pool.size).to be(0)
|
718
757
|
end
|
719
758
|
t.join
|
720
759
|
|
721
|
-
#expect(Mongo::Auth).to receive(:get).and_call_original
|
722
760
|
expect(pool.check_out).to be_a(Mongo::Server::Connection)
|
723
|
-
expect(
|
761
|
+
expect(pool.size).to be(1)
|
724
762
|
end
|
725
763
|
end
|
726
764
|
|
727
765
|
describe '#close_idle_sockets' do
|
728
|
-
|
729
766
|
let!(:pool) do
|
730
767
|
server.pool
|
731
768
|
end
|
@@ -733,7 +770,7 @@ describe Mongo::Server::ConnectionPool do
|
|
733
770
|
context 'when there is a max_idle_time specified' do
|
734
771
|
|
735
772
|
let(:options) do
|
736
|
-
{max_pool_size: 2, max_idle_time: 0.5}
|
773
|
+
{ max_pool_size: 2, max_idle_time: 0.5 }
|
737
774
|
end
|
738
775
|
|
739
776
|
after do
|
@@ -762,7 +799,7 @@ describe Mongo::Server::ConnectionPool do
|
|
762
799
|
context 'when min size is 0' do
|
763
800
|
|
764
801
|
let(:options) do
|
765
|
-
{max_pool_size: 2, min_pool_size: 0, max_idle_time: 0.5}
|
802
|
+
{ max_pool_size: 2, min_pool_size: 0, max_idle_time: 0.5 }
|
766
803
|
end
|
767
804
|
|
768
805
|
before do
|
@@ -782,9 +819,15 @@ describe Mongo::Server::ConnectionPool do
|
|
782
819
|
end
|
783
820
|
|
784
821
|
context 'when min size is > 0' do
|
822
|
+
before do
|
823
|
+
# Kill background thread to test close_idle_socket behavior
|
824
|
+
pool.stop_populator
|
825
|
+
expect(pool.instance_variable_get('@populator').running?).to be false
|
826
|
+
end
|
827
|
+
|
785
828
|
context 'when more than the number of min_size are checked out' do
|
786
829
|
let(:options) do
|
787
|
-
{max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5}
|
830
|
+
{ max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5 }
|
788
831
|
end
|
789
832
|
|
790
833
|
it 'closes and removes connections with idle sockets and does not connect new ones' do
|
@@ -813,7 +856,7 @@ describe Mongo::Server::ConnectionPool do
|
|
813
856
|
context 'when between 0 and min_size number of connections are checked out' do
|
814
857
|
|
815
858
|
let(:options) do
|
816
|
-
{max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5}
|
859
|
+
{ max_pool_size: 5, min_pool_size: 3, max_idle_time: 0.5 }
|
817
860
|
end
|
818
861
|
|
819
862
|
it 'closes and removes connections with idle sockets and does not connect new ones' do
|
@@ -855,8 +898,8 @@ describe Mongo::Server::ConnectionPool do
|
|
855
898
|
end
|
856
899
|
|
857
900
|
context 'when available connections include idle and non-idle ones' do
|
858
|
-
let(:
|
859
|
-
|
901
|
+
let (:options) do
|
902
|
+
{ max_pool_size: 2, max_idle_time: 0.5 }
|
860
903
|
end
|
861
904
|
|
862
905
|
let(:connection) do
|
@@ -866,25 +909,30 @@ describe Mongo::Server::ConnectionPool do
|
|
866
909
|
end
|
867
910
|
|
868
911
|
it 'disconnects all expired and only expired connections' do
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
912
|
+
# Since per-test cleanup will close the pool and disconnect
|
913
|
+
# the connection, we need to explicitly define the scope for the
|
914
|
+
# assertions
|
915
|
+
RSpec::Mocks.with_temporary_scope do
|
916
|
+
c1 = pool.check_out
|
917
|
+
expect(c1).to receive(:disconnect!)
|
918
|
+
c2 = pool.check_out
|
919
|
+
expect(c2).not_to receive(:disconnect!)
|
873
920
|
|
874
|
-
|
875
|
-
|
876
|
-
|
921
|
+
pool.check_in(c1)
|
922
|
+
Timecop.travel(Time.now + 1)
|
923
|
+
pool.check_in(c2)
|
877
924
|
|
878
|
-
|
879
|
-
|
925
|
+
expect(pool.size).to eq(2)
|
926
|
+
expect(pool.available_count).to eq(2)
|
880
927
|
|
881
|
-
|
882
|
-
|
928
|
+
expect(c1).not_to receive(:connect!)
|
929
|
+
expect(c2).not_to receive(:connect!)
|
883
930
|
|
884
|
-
|
931
|
+
pool.close_idle_sockets
|
885
932
|
|
886
|
-
|
887
|
-
|
933
|
+
expect(pool.size).to eq(1)
|
934
|
+
expect(pool.available_count).to eq(1)
|
935
|
+
end
|
888
936
|
end
|
889
937
|
end
|
890
938
|
|
@@ -897,13 +945,114 @@ describe Mongo::Server::ConnectionPool do
|
|
897
945
|
conn
|
898
946
|
end
|
899
947
|
|
948
|
+
it 'does not close any sockets' do
|
949
|
+
# Since per-test cleanup will close the pool and disconnect
|
950
|
+
# the connection, we need to explicitly define the scope for the
|
951
|
+
# assertions
|
952
|
+
RSpec::Mocks.with_temporary_scope do
|
953
|
+
expect(connection).not_to receive(:disconnect!)
|
954
|
+
pool.close_idle_sockets
|
955
|
+
expect(connection.connected?).to be(true)
|
956
|
+
end
|
957
|
+
end
|
958
|
+
end
|
959
|
+
end
|
960
|
+
|
961
|
+
describe '#populate' do
|
962
|
+
before do
|
963
|
+
# Disable the populator and clear the pool to isolate populate behavior
|
964
|
+
pool.stop_populator
|
965
|
+
pool.clear
|
966
|
+
end
|
967
|
+
|
968
|
+
let(:options) { {min_pool_size: 2, max_pool_size: 3} }
|
969
|
+
|
970
|
+
context 'when pool size is at least min_pool_size' do
|
900
971
|
before do
|
901
|
-
|
902
|
-
pool.
|
972
|
+
first_connection = pool.check_out
|
973
|
+
second_connection = pool.check_out
|
974
|
+
expect(pool.size).to eq 2
|
975
|
+
expect(pool.available_count).to eq 0
|
903
976
|
end
|
904
977
|
|
905
|
-
it 'does not
|
906
|
-
expect(
|
978
|
+
it 'does not create a connection and returns false' do
|
979
|
+
expect(pool.populate).to be false
|
980
|
+
expect(pool.size).to eq 2
|
981
|
+
expect(pool.available_count).to eq 0
|
982
|
+
end
|
983
|
+
end
|
984
|
+
|
985
|
+
context 'when pool size is less than min_pool_size' do
|
986
|
+
before do
|
987
|
+
first_connection = pool.check_out
|
988
|
+
expect(pool.size).to eq 1
|
989
|
+
expect(pool.available_count).to eq 0
|
990
|
+
end
|
991
|
+
|
992
|
+
it 'creates one connection, connects it, and returns true' do
|
993
|
+
expect(pool.populate).to be true
|
994
|
+
expect(pool.size).to eq 2
|
995
|
+
expect(pool.available_count).to eq 1
|
996
|
+
end
|
997
|
+
end
|
998
|
+
|
999
|
+
context 'when pool is closed' do
|
1000
|
+
before do
|
1001
|
+
pool.close
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it 'does not create a connection and returns false' do
|
1005
|
+
expect(pool.populate).to be false
|
1006
|
+
|
1007
|
+
# Can't just check pool size; size errors when pool is closed
|
1008
|
+
expect(pool.instance_variable_get('@available_connections').length).to eq(0)
|
1009
|
+
expect(pool.instance_variable_get('@checked_out_connections').length).to eq(0)
|
1010
|
+
expect(pool.instance_variable_get('@pending_connections').length).to eq(0)
|
1011
|
+
end
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
context 'when connect fails with socket related error once' do
|
1015
|
+
before do
|
1016
|
+
i = 0
|
1017
|
+
expect(pool).to receive(:connect_connection).exactly(:twice).and_wrap_original{ |m, *args|
|
1018
|
+
i += 1
|
1019
|
+
if i == 1
|
1020
|
+
raise Mongo::Error::SocketError
|
1021
|
+
else
|
1022
|
+
m.call(*args)
|
1023
|
+
end
|
1024
|
+
}
|
1025
|
+
expect(pool.size).to eq 0
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
it 'retries then succeeds in creating a connection' do
|
1029
|
+
expect(pool.populate).to be true
|
1030
|
+
expect(pool.size).to eq 1
|
1031
|
+
expect(pool.available_count).to eq 1
|
1032
|
+
end
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
context 'when connect fails with socket related error twice' do
|
1036
|
+
before do
|
1037
|
+
expect(pool).to receive(:connect_connection).exactly(:twice).and_raise(Mongo::Error::SocketError)
|
1038
|
+
expect(pool.size).to eq 0
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
it 'retries, raises the second error, and fails to create a connection' do
|
1042
|
+
expect{ pool.populate }.to raise_error(Mongo::Error::SocketError)
|
1043
|
+
expect(pool.size).to eq 0
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
context 'when connect fails with non socket related error' do
|
1048
|
+
before do
|
1049
|
+
expect(pool).to receive(:connect_connection).once.and_raise(Mongo::Auth::InvalidMechanism.new(""))
|
1050
|
+
expect(pool.size).to eq 0
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
it 'does not retry, raises the error, and fails to create a connection' do
|
1054
|
+
expect{ pool.populate }.to raise_error(Mongo::Auth::InvalidMechanism)
|
1055
|
+
expect(pool.size).to eq 0
|
907
1056
|
end
|
908
1057
|
end
|
909
1058
|
end
|