1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
# frozen_string_literal: true
# rubocop:todo all
require 'spec_helper'
describe 'Client after reconnect' do
let(:client) { authorized_client }
it 'is a functioning client' do
client['test'].insert_one('testk' => 'testv')
client.reconnect
doc = client['test'].find('testk' => 'testv').first
expect(doc).not_to be_nil
expect(doc['testk']).to eq('testv')
end
context 'non-lb' do
require_topology :single, :replica_set, :sharded
it 'recreates monitor thread' do
thread = client.cluster.servers.first.monitor.instance_variable_get('@thread')
expect(thread).to be_alive
thread.kill
# context switch to let the thread get killed
sleep 0.1
expect(thread).not_to be_alive
client.reconnect
new_thread = client.cluster.servers.first.monitor.instance_variable_get('@thread')
expect(new_thread).not_to eq(thread)
expect(new_thread).to be_alive
end
end
context 'lb' do
require_topology :load_balanced
it 'does not recreate monitor thread' do
thread = client.cluster.servers.first.monitor.instance_variable_get('@thread')
expect(thread).to be nil
client.reconnect
new_thread = client.cluster.servers.first.monitor.instance_variable_get('@thread')
expect(new_thread).to be nil
end
end
context 'with min_pool_size > 0' do
# This test causes live threads errors in jruby in other tests.
fails_on_jruby
let(:client) { authorized_client.with(min_pool_size: 1) }
it 'recreates connection pool populator thread' do
server = client.cluster.next_primary
thread = server.pool.populator.instance_variable_get('@thread')
expect(thread).to be_alive
thread.kill
# context switch to let the thread get killed
sleep 0.1
expect(thread).not_to be_alive
client.reconnect
new_server = client.cluster.next_primary
new_thread = new_server.pool.populator.instance_variable_get('@thread')
expect(new_thread).not_to eq(thread)
expect(new_thread).to be_alive
end
end
context 'SRV monitor thread' do
require_external_connectivity
let(:uri) do
"mongodb+srv://test1.test.build.10gen.cc/?tls=#{SpecConfig.instance.ssl?}"
end
# Debug logging to troubleshoot failures in Evergreen
let(:logger) do
Logger.new(STDERR). tap do |logger|
logger.level = :debug
end
end
let(:client) do
new_local_client(uri, SpecConfig.instance.monitoring_options.merge(
server_selection_timeout: 3.86, logger: logger))
end
let(:wait_for_discovery) do
client.cluster.next_primary
end
let(:wait_for_discovery_again) do
client.cluster.next_primary
end
shared_examples_for 'recreates SRV monitor' do
# JRuby produces this error:
# RSpec::Expectations::ExpectationNotMetError: expected nil to respond to `alive?`
# for this assertion:
# expect(thread).not_to be_alive
# This is bizarre because if thread was nil, the earlier call to
# thread.kill should've similarly failed, but it doesn't.
fails_on_jruby
minimum_mri_version '3.0.0'
it 'recreates SRV monitor' do
wait_for_discovery
expect(client.cluster.topology).to be_a(expected_topology_cls)
thread = client.cluster.srv_monitor.instance_variable_get('@thread')
expect(thread).to be_alive
thread.kill
# context switch to let the thread get killed
sleep 0.1
expect(thread).not_to be_alive
client.reconnect
wait_for_discovery_again
new_thread = client.cluster.srv_monitor.instance_variable_get('@thread')
expect(new_thread).not_to eq(thread)
expect(new_thread).to be_alive
end
end
context 'in sharded topology' do
require_topology :sharded
require_default_port_deployment
require_multi_mongos
let(:expected_topology_cls) { Mongo::Cluster::Topology::Sharded }
it_behaves_like 'recreates SRV monitor'
end
context 'in unknown topology' do
require_external_connectivity
# JRuby apparently does not implement non-blocking UDP I/O which is used
# by RubyDNS:
# NotImplementedError: recvmsg_nonblock is not implemented
fails_on_jruby
let(:uri) do
"mongodb+srv://test-fake.test.build.10gen.cc/"
end
let(:client) do
ClientRegistry.instance.register_local_client(
Mongo::Client.new(uri,
timeout: 5,
connect_timeout: 5,
server_selection_timeout: 3.89,
resolv_options: {
nameserver: 'localhost',
nameserver_port: [['localhost', 5300], ['127.0.0.1', 5300]],
},
logger: logger))
end
let(:expected_topology_cls) { Mongo::Cluster::Topology::Unknown }
let(:wait_for_discovery) do
# Since the entire test is done in unknown topology, we cannot use
# next_primary to wait for the client to discover the topology.
sleep 5
end
let(:wait_for_discovery_again) do
sleep 5
end
around do |example|
rules = [
['_mongodb._tcp.test-fake.test.build.10gen.cc', :srv,
[0, 0, 2799, 'localhost.test.build.10gen.cc'],
],
]
mock_dns(rules) do
example.run
end
end
it_behaves_like 'recreates SRV monitor'
end
end
end
|