mongo 2.14.0 → 2.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongo/background_thread.rb +11 -0
  4. data/lib/mongo/cluster/sdam_flow.rb +14 -0
  5. data/lib/mongo/cluster.rb +0 -26
  6. data/lib/mongo/collection/view/iterable.rb +16 -6
  7. data/lib/mongo/collection.rb +2 -0
  8. data/lib/mongo/cursor.rb +10 -0
  9. data/lib/mongo/database.rb +14 -2
  10. data/lib/mongo/grid/fs_bucket.rb +37 -37
  11. data/lib/mongo/operation/parallel_scan/command.rb +1 -2
  12. data/lib/mongo/operation/shared/read_preference_supported.rb +38 -36
  13. data/lib/mongo/operation/shared/sessions_supported.rb +3 -2
  14. data/lib/mongo/protocol/msg.rb +2 -2
  15. data/lib/mongo/protocol/query.rb +11 -11
  16. data/lib/mongo/server/connection_pool.rb +0 -2
  17. data/lib/mongo/server.rb +0 -14
  18. data/lib/mongo/server_selector/secondary_preferred.rb +2 -7
  19. data/lib/mongo/srv/monitor.rb +0 -11
  20. data/lib/mongo/version.rb +1 -1
  21. data/spec/integration/query_cache_spec.rb +45 -0
  22. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  23. data/spec/integration/sdam_events_spec.rb +3 -5
  24. data/spec/integration/secondary_reads_spec.rb +102 -0
  25. data/spec/mongo/cluster_spec.rb +2 -18
  26. data/spec/mongo/index/view_spec.rb +4 -2
  27. data/spec/mongo/operation/read_preference_legacy_spec.rb +9 -19
  28. data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
  29. data/spec/mongo/server/app_metadata_shared.rb +33 -7
  30. data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
  31. data/spec/runners/transactions/operation.rb +13 -2
  32. data/spec/shared/bin/get-mongodb-download-url +17 -0
  33. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  34. data/spec/shared/lib/mrss/constraints.rb +43 -0
  35. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  36. data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
  37. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  38. data/spec/shared/lib/mrss/spec_organizer.rb +3 -0
  39. data/spec/shared/lib/mrss/utils.rb +15 -0
  40. data/spec/shared/share/Dockerfile.erb +231 -0
  41. data/spec/shared/shlib/distro.sh +73 -0
  42. data/spec/shared/shlib/server.sh +290 -0
  43. data/spec/shared/shlib/set_env.sh +128 -0
  44. data/spec/solo/clean_exit_spec.rb +21 -0
  45. data/spec/support/client_registry.rb +8 -4
  46. data/spec/support/client_registry_macros.rb +4 -4
  47. data/spec/support/spec_config.rb +12 -0
  48. data/spec/support/spec_setup.rb +48 -38
  49. data.tar.gz.sig +0 -0
  50. metadata +1005 -983
  51. metadata.gz.sig +0 -0
@@ -684,8 +684,6 @@ module Mongo
684
684
  # @return [ Proc ] The Finalizer.
685
685
  def self.finalize(available_connections, pending_connections, populator)
686
686
  proc do
687
- populator.stop!
688
-
689
687
  available_connections.each do |connection|
690
688
  connection.disconnect!(reason: :pool_closed)
691
689
  end
data/lib/mongo/server.rb CHANGED
@@ -272,19 +272,6 @@ module Mongo
272
272
  @connected
273
273
  end
274
274
 
275
- # When the server is flagged for garbage collection, stop the monitor
276
- # thread.
277
- #
278
- # @example Finalize the object.
279
- # Server.finalize(monitor)
280
- #
281
- # @param [ Server::Monitor ] monitor The server monitor.
282
- #
283
- # @since 2.2.0
284
- def self.finalize(monitor)
285
- proc { monitor.stop! }
286
- end
287
-
288
275
  # Start monitoring the server.
289
276
  #
290
277
  # Used internally by the driver to add a server to a cluster
@@ -297,7 +284,6 @@ module Mongo
297
284
  Monitoring::Event::ServerOpening.new(address, cluster.topology)
298
285
  )
299
286
  if options[:monitoring_io] != false
300
- ObjectSpace.define_finalizer(self, self.class.finalize(monitor))
301
287
  monitor.run!
302
288
  end
303
289
  end
@@ -86,13 +86,8 @@ module Mongo
86
86
  #
87
87
  # @since 2.0.0
88
88
  def to_mongos
89
- if tag_sets.empty? && max_staleness.nil? && hedge.nil?
90
- # The server preference is not sent to mongos as part of the query
91
- # selector if there are no tag sets, for maximum backwards compatibility.
92
- nil
93
- else
94
- to_doc
95
- end
89
+ # Always send the read preference to mongos: DRIVERS-1642.
90
+ to_doc
96
91
  end
97
92
 
98
93
  private
@@ -59,11 +59,6 @@ module Mongo
59
59
  # records' TTL values.
60
60
  attr_reader :last_result
61
61
 
62
- def start!
63
- super
64
- ObjectSpace.define_finalizer(self, self.class.finalize(@thread))
65
- end
66
-
67
62
  private
68
63
 
69
64
  def do_work
@@ -97,12 +92,6 @@ module Mongo
97
92
  @cluster.set_server_list(last_result.address_strs)
98
93
  end
99
94
 
100
- def self.finalize(thread)
101
- Proc.new do
102
- thread.kill
103
- end
104
- end
105
-
106
95
  def scan_interval
107
96
  if last_result.empty?
108
97
  [cluster.heartbeat_interval, MIN_SCAN_INTERVAL].min
data/lib/mongo/version.rb CHANGED
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.14.0'.freeze
20
+ VERSION = '2.14.1'.freeze
21
21
  end
@@ -1042,4 +1042,49 @@ describe 'QueryCache' do
1042
1042
  expect(events.length).to eq(2)
1043
1043
  end
1044
1044
  end
1045
+
1046
+ context 'when result set has multiple documents and cursor is iterated partially' do
1047
+
1048
+ before do
1049
+ Mongo::QueryCache.enabled = false
1050
+ 5.times do
1051
+ authorized_collection.insert_one({ name: 'testing' })
1052
+ end
1053
+ end
1054
+
1055
+ shared_examples 'retrieves full result set on second iteration' do
1056
+ it 'retrieves full result set on second iteration' do
1057
+ Mongo::QueryCache.clear
1058
+ Mongo::QueryCache.enabled = true
1059
+
1060
+ partial_first_iteration
1061
+
1062
+ authorized_collection.find.to_a.length.should == 5
1063
+ end
1064
+
1065
+ end
1066
+
1067
+ context 'using each & break' do
1068
+ let(:partial_first_iteration) do
1069
+ called = false
1070
+ authorized_collection.find.each do
1071
+ called = true
1072
+ break
1073
+ end
1074
+ called.should be true
1075
+ end
1076
+
1077
+ include_examples 'retrieves full result set on second iteration'
1078
+ end
1079
+
1080
+ context 'using next' do
1081
+ let(:partial_first_iteration) do
1082
+ # #next is executed in its own fiber, and query cache is disabled
1083
+ # for that operation.
1084
+ authorized_collection.find.to_enum.next
1085
+ end
1086
+
1087
+ include_examples 'retrieves full result set on second iteration'
1088
+ end
1089
+ end
1045
1090
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'SDAM error handling' do
4
- clean_slate_for_all
4
+ clean_slate
5
5
 
6
6
  after do
7
7
  # Close all clients after every test to avoid leaking expectations into
@@ -67,10 +67,8 @@ describe 'SDAM events' do
67
67
  started_events.length.should <= 10
68
68
 
69
69
  succeeded_events = subscriber.select_succeeded_events(Mongo::Monitoring::Event::ServerHeartbeatSucceeded)
70
- # Since we gracefully close the client, we expect each heartbeat
71
- # to complete.
72
70
  started_events.length.should > 1
73
- (succeeded_events.length-1..succeeded_events.length).should include(started_events.length)
71
+ (succeeded_events.length..succeeded_events.length+1).should include(started_events.length)
74
72
  end
75
73
  end
76
74
 
@@ -109,9 +107,9 @@ describe 'SDAM events' do
109
107
  # There may be in-flight ismasters that don't complete, both
110
108
  # regular and awaited.
111
109
  started_awaited.length.should > 1
112
- (succeeded_awaited.length-1..succeeded_awaited.length).should include(started_awaited.length)
110
+ (succeeded_awaited.length..succeeded_awaited.length+1).should include(started_awaited.length)
113
111
  started_regular.length.should > 1
114
- (succeeded_regular.length-1..succeeded_regular.length).should include(started_regular.length)
112
+ (succeeded_regular.length..succeeded_regular.length+1).should include(started_regular.length)
115
113
  end
116
114
  end
117
115
  end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Secondary reads' do
4
+ before do
5
+ root_authorized_client.use('sr')['secondary_reads'].drop
6
+ root_authorized_client.use('sr')['secondary_reads'].insert_one(test: 1)
7
+ end
8
+
9
+ shared_examples 'performs reads as per read preference' do
10
+
11
+ %i(primary primary_preferred).each do |mode|
12
+
13
+ context mode.inspect do
14
+
15
+ let(:client) do
16
+ root_authorized_client.with(read: {mode: mode}).use('sr')
17
+ end
18
+
19
+ it 'reads from primary' do
20
+ start_stats = get_read_counters
21
+
22
+ 30.times do
23
+ client['secondary_reads'].find.to_a
24
+ end
25
+
26
+ end_stats = get_read_counters
27
+
28
+ end_stats[:secondary].should be_within(10).of(start_stats[:secondary])
29
+ end_stats[:primary].should >= start_stats[:primary] + 30
30
+ end
31
+ end
32
+ end
33
+
34
+ %i(secondary secondary_preferred).each do |mode|
35
+
36
+ context mode.inspect do
37
+ let(:client) do
38
+ root_authorized_client.with(read: {mode: mode}).use('sr')
39
+ end
40
+
41
+ it 'reads from secondaries' do
42
+ start_stats = get_read_counters
43
+
44
+ 30.times do
45
+ client['secondary_reads'].find.to_a
46
+ end
47
+
48
+ end_stats = get_read_counters
49
+
50
+ end_stats[:primary].should be_within(10).of(start_stats[:primary])
51
+ end_stats[:secondary].should >= start_stats[:secondary] + 30
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'replica set' do
58
+ require_topology :replica_set
59
+
60
+ include_examples 'performs reads as per read preference'
61
+ end
62
+
63
+ context 'sharded cluster' do
64
+ require_topology :sharded
65
+
66
+ include_examples 'performs reads as per read preference'
67
+ end
68
+
69
+ def get_read_counters
70
+ client = ClientRegistry.instance.global_client('root_authorized')
71
+ addresses = []
72
+ if client.cluster.sharded?
73
+ doc = client.use('admin').command(listShards: 1).documents.first
74
+ doc['shards'].each do |shard|
75
+ addresses += shard['host'].split('/').last.split(',')
76
+ end
77
+ else
78
+ client.cluster.servers.each do |server|
79
+ next unless server.primary? || server.secondary?
80
+ addresses << server.address.seed
81
+ end
82
+ end
83
+ stats = Hash.new(0)
84
+ addresses.each do |address|
85
+ ClientRegistry.instance.new_local_client(
86
+ [address],
87
+ SpecConfig.instance.all_test_options.merge(connect: :direct),
88
+ ) do |c|
89
+ server = c.cluster.servers.first
90
+ next unless server.primary? || server.secondary?
91
+ stat = c.command(serverStatus: 1).documents.first
92
+ queries = stat['opcounters']['query']
93
+ if server.primary?
94
+ stats[:primary] += queries
95
+ else
96
+ stats[:secondary] += queries
97
+ end
98
+ end
99
+ end
100
+ stats
101
+ end
102
+ end
@@ -274,27 +274,11 @@ describe Mongo::Cluster do
274
274
 
275
275
  describe '#add' do
276
276
 
277
- context 'when topology is Single' do
278
-
279
- let(:cluster) { cluster_with_semaphore }
280
-
281
- let(:topology) do
282
- Mongo::Cluster::Topology::Single.new({}, cluster)
283
- end
284
-
285
- before do
286
- cluster.add('a')
287
- end
288
-
289
- it 'does not add discovered servers to the cluster' do
290
- expect(cluster.servers[0].address.seed).to_not eq('a')
291
- end
292
- end
293
-
294
277
  context 'topology is Sharded' do
278
+ require_topology :sharded
295
279
 
296
280
  let(:topology) do
297
- Mongo::Cluster::Topology::Single.new({}, cluster)
281
+ Mongo::Cluster::Topology::Sharded.new({}, cluster)
298
282
  end
299
283
 
300
284
  before do
@@ -305,7 +305,8 @@ describe Mongo::Index::View do
305
305
  { key: { testing: -1 }, unique: true },
306
306
  { commit_quorum: 'unsupported-value' }
307
307
  )
308
- end.to raise_error(Mongo::Error::OperationFailure, /Commit quorum cannot be satisfied with the current replica set configuration/)
308
+ # 4.4.4 changed the text of the error message
309
+ end.to raise_error(Mongo::Error::OperationFailure, /Commit quorum cannot be satisfied with the current replica set configuration|No write concern mode named 'unsupported-value' found in replica set configuration/)
309
310
  end
310
311
  end
311
312
  end
@@ -964,7 +965,8 @@ describe Mongo::Index::View do
964
965
  it 'raises an exception' do
965
966
  expect do
966
967
  view.create_one({ 'x' => 1 }, commit_quorum: 'unsupported-value')
967
- end.to raise_error(Mongo::Error::OperationFailure, /Commit quorum cannot be satisfied with the current replica set configuration/)
968
+ # 4.4.4 changed the text of the error message
969
+ end.to raise_error(Mongo::Error::OperationFailure, /Commit quorum cannot be satisfied with the current replica set configuration|No write concern mode named 'unsupported-value' found in replica set configuration/)
968
970
  end
969
971
  end
970
972
  end
@@ -46,10 +46,10 @@ describe Mongo::Operation::ReadPreferenceSupported do
46
46
  end
47
47
  end
48
48
 
49
- describe '#add_slave_ok_flag_maybe' do
49
+ describe '#add_slave_ok_flag?' do
50
50
 
51
51
  let(:actual) do
52
- operation.send(:add_slave_ok_flag_maybe, operation.send(:options), connection)
52
+ operation.send(:add_slave_ok_flag?, connection)
53
53
  end
54
54
 
55
55
  shared_examples_for 'sets the slave_ok flag as expected' do
@@ -60,9 +60,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
60
60
 
61
61
  shared_examples_for 'never sets slave_ok' do
62
62
 
63
- let(:expected) do
64
- { }
65
- end
63
+ let(:expected) { false }
66
64
 
67
65
  context 'when no read preference is specified' do
68
66
  let(:read_pref) { Mongo::ServerSelector.get }
@@ -85,9 +83,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
85
83
 
86
84
  shared_examples_for 'always sets slave_ok' do
87
85
 
88
- let(:expected) do
89
- { :flags => [ :slave_ok ] }
90
- end
86
+ let(:expected) { true }
91
87
 
92
88
  context 'when no read preference is specified' do
93
89
  let(:read_pref) { Mongo::ServerSelector.get }
@@ -114,9 +110,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
114
110
 
115
111
  let(:read_pref) { Mongo::ServerSelector.get }
116
112
 
117
- let(:expected) do
118
- { }
119
- end
113
+ let(:expected) { false }
120
114
 
121
115
  it_behaves_like 'sets the slave_ok flag as expected'
122
116
  end
@@ -127,9 +121,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
127
121
 
128
122
  let(:read_pref) { Mongo::ServerSelector.get(:mode => :secondary) }
129
123
 
130
- let(:expected) do
131
- { :flags => [ :slave_ok ] }
132
- end
124
+ let(:expected) { true }
133
125
 
134
126
  it_behaves_like 'sets the slave_ok flag as expected'
135
127
  end
@@ -138,9 +130,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
138
130
 
139
131
  let(:read_pref) { Mongo::ServerSelector.get(:mode => :primary) }
140
132
 
141
- let(:expected) do
142
- { }
143
- end
133
+ let(:expected) { false }
144
134
 
145
135
  it_behaves_like 'sets the slave_ok flag as expected'
146
136
  end
@@ -206,7 +196,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
206
196
  end
207
197
  end
208
198
 
209
- describe '#update_selector_for_read_pref' do
199
+ describe '#add_read_preference_legacy' do
210
200
 
211
201
  let(:read_pref) do
212
202
  Mongo::ServerSelector.get(:mode => mode)
@@ -215,7 +205,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
215
205
  # Behavior of sending $readPreference is the same regardless of topology.
216
206
  shared_examples_for '$readPreference in the command' do
217
207
  let(:actual) do
218
- operation.send(:update_selector_for_read_pref, operation.send(:selector), connection)
208
+ operation.send(:add_read_preference_legacy, operation.send(:selector), connection)
219
209
  end
220
210
 
221
211
  let(:expected_read_preference) do
@@ -175,13 +175,13 @@ describe Mongo::Operation::SessionsSupported do
175
175
  let(:tag_sets) { nil }
176
176
 
177
177
  context 'without tag_sets specified' do
178
- it_behaves_like 'does not modify selector'
178
+ it_behaves_like 'adds read preference'
179
179
  end
180
180
 
181
181
  context 'with empty tag_sets' do
182
182
  let(:tag_sets) { [] }
183
183
 
184
- it_behaves_like 'does not modify selector'
184
+ it_behaves_like 'adds read preference'
185
185
  end
186
186
 
187
187
  context 'with tag_sets specified' do
@@ -256,7 +256,7 @@ describe Mongo::Operation::SessionsSupported do
256
256
  let(:hedge) { nil }
257
257
 
258
258
  context 'when tag_sets and hedge are not specified' do
259
- it_behaves_like 'does not modify selector'
259
+ it_behaves_like 'adds read preference'
260
260
  end
261
261
 
262
262
  context 'when tag_sets are specified' do
@@ -8,14 +8,40 @@ shared_examples 'app metadata document' do
8
8
  document[:client][:driver][:version].should == Mongo::VERSION
9
9
  end
10
10
 
11
- it 'includes operating system information' do
12
- document[:client][:os][:type].should == 'linux'
13
- if BSON::Environment.jruby? || RUBY_VERSION >= '3.0'
14
- document[:client][:os][:name].should == 'linux'
15
- else
16
- document[:client][:os][:name].should == 'linux-gnu'
11
+ context 'linux' do
12
+ before(:all) do
13
+ unless SpecConfig.instance.linux?
14
+ skip "Linux required, we have #{RbConfig::CONFIG['host_os']}"
15
+ end
16
+ end
17
+
18
+ it 'includes operating system information' do
19
+ document[:client][:os][:type].should == 'linux'
20
+ if BSON::Environment.jruby? || RUBY_VERSION >= '3.0'
21
+ document[:client][:os][:name].should == 'linux'
22
+ else
23
+ document[:client][:os][:name].should == 'linux-gnu'
24
+ end
25
+ document[:client][:os][:architecture].should == 'x86_64'
26
+ end
27
+ end
28
+
29
+ context 'macos' do
30
+ before(:all) do
31
+ unless SpecConfig.instance.macos?
32
+ skip "MacOS required, we have #{RbConfig::CONFIG['host_os']}"
33
+ end
34
+ end
35
+
36
+ it 'includes operating system information' do
37
+ document[:client][:os][:type].should == 'darwin'
38
+ if BSON::Environment.jruby?
39
+ document[:client][:os][:name].should == 'darwin'
40
+ else
41
+ document[:client][:os][:name].should =~ /darwin\d+/
42
+ end
43
+ document[:client][:os][:architecture].should == 'x86_64'
17
44
  end
18
- document[:client][:os][:architecture].should == 'x86_64'
19
45
  end
20
46
 
21
47
  context 'mri' do