Skip to content

Commit cccc669

Browse files
authored
Fix RUBY-1442 Topology(Description) has no server knowledge (#1121)
* Fix RUBY-1442 Topology(Description) has no server knowledge * Redo server descriptions as a hash
1 parent 33bf9af commit cccc669

23 files changed

+151
-39
lines changed

lib/mongo/cluster.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,14 @@ def initialize(seeds, monitoring, options = Options::Redacted.new)
120120
add(seed, monitor: false)
121121
end
122122

123-
publish_sdam_event(
124-
Monitoring::TOPOLOGY_CHANGED,
125-
Monitoring::Event::TopologyChanged.new(opening_topology, @topology)
126-
) if seeds.size >= 1
123+
if seeds.size >= 1
124+
# Recreate the topology to get the current server list into it
125+
@topology = topology.class.new(topology.options, topology.monitoring, self)
126+
publish_sdam_event(
127+
Monitoring::TOPOLOGY_CHANGED,
128+
Monitoring::Event::TopologyChanged.new(opening_topology, @topology)
129+
)
130+
end
127131

128132
servers.each do |server|
129133
server.start_monitoring

lib/mongo/cluster/sdam_flow.rb

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ def commit_changes
413413

414414
topology_changed_event_published = false
415415
if topology.object_id != cluster.topology.object_id || @need_topology_changed_event
416+
# We are about to publish topology changed event.
417+
# Recreate the topology instance to get its server descriptions
418+
# up to date.
419+
@topology = topology.class.new(topology.options, topology.monitoring, cluster)
416420
# This sends the SDAM event
417421
cluster.update_topology(topology)
418422
topology_changed_event_published = true
@@ -433,15 +437,13 @@ def commit_changes
433437
return
434438
end
435439

436-
# TODO previous and updated topologies should differ in
437-
# their server descriptions but currently they are the same
438-
# exact object - https://jira.mongodb.org/browse/RUBY-1442
439-
# and https://jira.mongodb.org/browse/RUBY-1519
440-
publish_sdam_event(
441-
::Mongo::Monitoring::TOPOLOGY_CHANGED,
442-
::Mongo::Monitoring::Event::TopologyChanged.new(topology, topology)
443-
)
444-
@previous_desc = updated_desc
440+
# If we are here, there has been a change in the server descriptions
441+
# in our topology, but topology class has not changed.
442+
# Publish the topology changed event and recreate the topology to
443+
# get the new list of server descriptions into it.
444+
@topology = topology.class.new(topology.options, topology.monitoring, cluster)
445+
# This sends the SDAM event
446+
cluster.update_topology(topology)
445447
end
446448

447449
# Checks if the cluster has a primary, and if not, transitions the topology

lib/mongo/cluster/topology/base.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ def initialize(options, monitoring, cluster)
5656
@options = options
5757
@monitoring = monitoring
5858
@cluster = cluster
59+
# The list of server descriptions is simply fixed at the time of
60+
# topology creation. If server description change later, a
61+
# new topology instance should be created.
62+
@server_descriptions = {}
63+
cluster.servers_list.each do |server|
64+
@server_descriptions[server.address.to_s] = server.description
65+
end
5966
end
6067

6168
# @return [ Hash ] options The options.
@@ -74,6 +81,12 @@ def addresses
7481
# @return [ monitoring ] monitoring the monitoring.
7582
attr_reader :monitoring
7683

84+
# @return [ Hash ] server_descriptions The map of address strings to
85+
# server descriptions, one for each server in the cluster.
86+
#
87+
# @since 2.7.0
88+
attr_reader :server_descriptions
89+
7790
# The largest electionId ever reported by a primary.
7891
# May be nil.
7992
#

spec/mongo/cluster/topology/replica_set_spec.rb

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
Mongo::Monitoring.new(monitoring: false)
1515
end
1616

17+
# Cluster needs a topology and topology needs a cluster...
18+
# This temporary cluster is used for topology construction.
19+
let(:temp_cluster) do
20+
double('temp cluster').tap do |cluster|
21+
allow(cluster).to receive(:servers_list).and_return([])
22+
end
23+
end
24+
1725
let(:cluster) do
1826
double('cluster').tap do |cl|
1927
allow(cl).to receive(:topology).and_return(topology)
@@ -66,7 +74,7 @@
6674
context 'when a replica set name is provided' do
6775

6876
let(:topology) do
69-
described_class.new({ :replica_set_name => 'testing' }, monitoring, nil)
77+
described_class.new({ :replica_set_name => 'testing' }, monitoring, temp_cluster)
7078
end
7179

7280
let(:servers) do
@@ -82,21 +90,21 @@
8290
describe '.replica_set?' do
8391

8492
it 'returns true' do
85-
expect(described_class.new({replica_set_name: 'foo'}, monitoring, nil)).to be_replica_set
93+
expect(described_class.new({replica_set_name: 'foo'}, monitoring, temp_cluster)).to be_replica_set
8694
end
8795
end
8896

8997
describe '.sharded?' do
9098

9199
it 'returns false' do
92-
expect(described_class.new({replica_set_name: 'foo'}, monitoring, nil)).to_not be_sharded
100+
expect(described_class.new({replica_set_name: 'foo'}, monitoring, temp_cluster)).to_not be_sharded
93101
end
94102
end
95103

96104
describe '.single?' do
97105

98106
it 'returns false' do
99-
expect(described_class.new({replica_set_name: 'foo'}, monitoring, nil)).to_not be_single
107+
expect(described_class.new({replica_set_name: 'foo'}, monitoring, temp_cluster)).to_not be_single
100108
end
101109
end
102110

@@ -105,7 +113,7 @@
105113

106114
it 'returns value given in constructor options' do
107115
topology = described_class.new({replica_set_name: 'foo', max_election_id: election_id},
108-
monitoring, nil)
116+
monitoring, temp_cluster)
109117

110118
expect(topology.max_election_id).to eql(election_id)
111119
end
@@ -114,7 +122,7 @@
114122
describe '#max_set_version' do
115123
it 'returns value given in constructor options' do
116124
topology = described_class.new({replica_set_name: 'foo', max_set_version: 5},
117-
monitoring, nil)
125+
monitoring, temp_cluster)
118126

119127
expect(topology.max_set_version).to eq(5)
120128
end
@@ -123,7 +131,7 @@
123131
describe '#has_readable_servers?' do
124132

125133
let(:topology) do
126-
described_class.new({replica_set_name: 'foo'}, monitoring, [])
134+
described_class.new({replica_set_name: 'foo'}, monitoring, temp_cluster)
127135
end
128136

129137
let(:cluster) do
@@ -290,7 +298,7 @@
290298
describe '#has_writable_servers?' do
291299

292300
let(:topology) do
293-
described_class.new({replica_set_name: 'foo'}, monitoring, [])
301+
described_class.new({replica_set_name: 'foo'}, monitoring, temp_cluster)
294302
end
295303

296304
context 'when a primary server exists' do
@@ -331,7 +339,7 @@
331339
describe '#new_max_set_version' do
332340
context 'initially nil' do
333341
let(:topology) do
334-
described_class.new({replica_set_name: 'foo'}, monitoring, nil).tap do |topology|
342+
described_class.new({replica_set_name: 'foo'}, monitoring, temp_cluster).tap do |topology|
335343
expect(topology.max_set_version).to be nil
336344
end
337345
end
@@ -364,7 +372,7 @@
364372
context 'initially not nil' do
365373
let(:topology) do
366374
described_class.new({replica_set_name: 'foo', max_set_version: 4},
367-
monitoring, nil
375+
monitoring, temp_cluster
368376
).tap do |topology|
369377
expect(topology.max_set_version).to eq(4)
370378
end
@@ -411,7 +419,9 @@
411419
describe '#new_max_election_id' do
412420
context 'initially nil' do
413421
let(:topology) do
414-
described_class.new({replica_set_name: 'foo'}, monitoring, nil).tap do |topology|
422+
described_class.new({replica_set_name: 'foo'},
423+
monitoring, temp_cluster,
424+
).tap do |topology|
415425
expect(topology.max_election_id).to be nil
416426
end
417427
end
@@ -448,7 +458,7 @@
448458

449459
let(:topology) do
450460
described_class.new({replica_set_name: 'foo', max_election_id: old_election_id},
451-
monitoring, nil
461+
monitoring, temp_cluster,
452462
).tap do |topology|
453463
expect(topology.max_election_id).to be old_election_id
454464
end

spec/mongo/cluster/topology/sharded_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@
66
Mongo::Address.new('127.0.0.1:27017')
77
end
88

9+
# Cluster needs a topology and topology needs a cluster...
10+
# This temporary cluster is used for topology construction.
11+
let(:temp_cluster) do
12+
double('temp cluster').tap do |cluster|
13+
allow(cluster).to receive(:servers_list).and_return([])
14+
end
15+
end
16+
917
let(:topology) do
10-
described_class.new({}, monitoring, nil)
18+
described_class.new({}, monitoring, temp_cluster)
1119
end
1220

1321
let(:monitoring) do

spec/mongo/cluster/topology/single_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,16 @@
1010
Mongo::Monitoring.new(monitoring: false)
1111
end
1212

13+
# Cluster needs a topology and topology needs a cluster...
14+
# This temporary cluster is used for topology construction.
15+
let(:temp_cluster) do
16+
double('temp cluster').tap do |cluster|
17+
allow(cluster).to receive(:servers_list).and_return([])
18+
end
19+
end
20+
1321
let(:topology) do
14-
described_class.new({}, monitoring, nil)
22+
described_class.new({}, monitoring, temp_cluster)
1523
end
1624

1725
let(:listeners) do

spec/mongo/cluster/topology/unknown_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@
66
Mongo::Monitoring.new(monitoring: false)
77
end
88

9+
# Cluster needs a topology and topology needs a cluster...
10+
# This temporary cluster is used for topology construction.
11+
let(:temp_cluster) do
12+
double('temp cluster').tap do |cluster|
13+
allow(cluster).to receive(:servers_list).and_return([])
14+
end
15+
end
16+
917
let(:topology) do
10-
described_class.new({}, monitoring, nil)
18+
described_class.new({}, monitoring, temp_cluster)
1119
end
1220

1321
describe '.servers' do

spec/mongo/cluster_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@
190190
context 'when the cluster has no servers' do
191191

192192
let(:servers) do
193-
[nil]
193+
[]
194194
end
195195

196196
before do

spec/mongo/monitoring/event/server_closed_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
let(:cluster) do
1212
double('cluster').tap do |cluster|
1313
allow(cluster).to receive(:addresses).and_return([address])
14+
allow(cluster).to receive(:servers_list).and_return([])
1415
end
1516
end
1617

spec/mongo/monitoring/event/server_description_changed_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
let(:cluster) do
1212
double('cluster').tap do |cluster|
1313
allow(cluster).to receive(:addresses).and_return([address])
14+
allow(cluster).to receive(:servers_list).and_return([])
1415
end
1516
end
1617

0 commit comments

Comments
 (0)