mongo 2.10.5 → 2.11.0.rc0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|