mongo 2.17.0 → 2.17.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7fed7eef29657f665e0b2cbecaab0e60626e76aad58087ff5fd8d051d237002
4
- data.tar.gz: 77e80dd97d3d60c6836b563233f23d1f505344905d87ff8afedbe31fa45b216a
3
+ metadata.gz: 1a38f748fe8350d12ecfd23a30e794b65addcfbf8f5303504f5f85999e2c2b0d
4
+ data.tar.gz: 876f431a9bfc558ecad0006a32b6ed90b6a94d05ac553a52fbc8b5d3b2b80a55
5
5
  SHA512:
6
- metadata.gz: 4a898c56e637b3c0597126cc207d9c70ae9f0b3533294fab7ba92f8882be72a5df44ead386e055433966b40ad7f34ef3d0a5a82ae1c9b3088d4fb2d428673ee8
7
- data.tar.gz: abec048d264aee514a33c660f0ac151f169f6b764d7e85c91f626a1ecb30e2b27c9ddcf3aa404c0f3e3cc27eb8f00dfe0e223a69096755556cb4942c5be9ce3f
6
+ metadata.gz: 256181a9c42fee1b029c899ab56a1a1f5b5283d4071913fc5777ad185f5349a00dc1fa36ac60b9b203a15f1d0857511c551f417f78864a04899e973e8da14b96
7
+ data.tar.gz: 1272cc35779781fe390276007c831e653b64087e1f34b0459e12d8dfea7099dd39be4e06cef347e36fa7222064ba2f267a5be4a48120d6017f4424876123195b
checksums.yaml.gz.sig CHANGED
Binary file
@@ -44,6 +44,7 @@ module Mongo
44
44
  @to_kill = {}
45
45
  @active_cursor_ids = Set.new
46
46
  @mutex = Mutex.new
47
+ @kill_spec_queue = Queue.new
47
48
  end
48
49
 
49
50
  attr_reader :cluster
@@ -51,17 +52,10 @@ module Mongo
51
52
  # Schedule a kill cursors operation to be eventually executed.
52
53
  #
53
54
  # @param [ Cursor::KillSpec ] kill_spec The kill specification.
54
- # @param [ Mongo::Server ] server The server to send the kill cursors
55
- # operation to.
56
55
  #
57
56
  # @api private
58
- def schedule_kill_cursor(kill_spec, server)
59
- @mutex.synchronize do
60
- if @active_cursor_ids.include?(kill_spec.cursor_id)
61
- @to_kill[server.address.seed] ||= Set.new
62
- @to_kill[server.address.seed] << kill_spec
63
- end
64
- end
57
+ def schedule_kill_cursor(kill_spec)
58
+ @kill_spec_queue << kill_spec
65
59
  end
66
60
 
67
61
  # Register a cursor id as active.
@@ -110,6 +104,24 @@ module Mongo
110
104
  end
111
105
  end
112
106
 
107
+ # Read and decode scheduled kill cursors operations.
108
+ #
109
+ # This method mutates instance variables without locking, so is is not
110
+ # thread safe. Generally, it should not be called itself, this is a helper
111
+ # for `kill_cursor` method.
112
+ #
113
+ # @api private
114
+ def read_scheduled_kill_specs
115
+ while kill_spec = @kill_spec_queue.pop(true)
116
+ if @active_cursor_ids.include?(kill_spec.cursor_id)
117
+ @to_kill[kill_spec.server_address] ||= Set.new
118
+ @to_kill[kill_spec.server_address] << kill_spec
119
+ end
120
+ end
121
+ rescue ThreadError
122
+ # Empty queue, nothing to do.
123
+ end
124
+
113
125
  # Execute all pending kill cursors operations.
114
126
  #
115
127
  # @example Execute pending kill cursors operations.
@@ -122,14 +134,14 @@ module Mongo
122
134
  # TODO optimize this to batch kill cursor operations for the same
123
135
  # server/database/collection instead of killing each cursor
124
136
  # individually.
125
-
126
137
  loop do
127
- server_address_str = nil
138
+ server_address = nil
128
139
 
129
140
  kill_spec = @mutex.synchronize do
141
+ read_scheduled_kill_specs
130
142
  # Find a server that has any cursors scheduled for destruction.
131
- server_address_str, specs =
132
- @to_kill.detect { |server_address_str, specs| specs.any? }
143
+ server_address, specs =
144
+ @to_kill.detect { |_, specs| specs.any? }
133
145
 
134
146
  if specs.nil?
135
147
  # All servers have empty specs, nothing to do.
@@ -168,7 +180,7 @@ module Mongo
168
180
  op = Operation::KillCursors.new(spec)
169
181
 
170
182
  server = cluster.servers.detect do |server|
171
- server.address.seed == server_address_str
183
+ server.address == server_address
172
184
  end
173
185
 
174
186
  unless server
@@ -115,11 +115,14 @@ module Mongo
115
115
  end
116
116
  command.update(view_options)
117
117
  command.update(options.slice(:collation))
118
+
118
119
  # Read preference isn't simply passed in the command payload
119
- # (it may need to be converted to wire protocol flags)
120
- # so remove it here and hopefully it's handled elsewhere.
121
- # If not, RUBY-2706.
122
- command.delete(:read)
120
+ # (it may need to be converted to wire protocol flags).
121
+ # Ideally it should be removed here, however due to Mongoid 7
122
+ # using this method and requiring :read to be returned from it,
123
+ # we cannot do this just yet - see RUBY-2932.
124
+ #command.delete(:read)
125
+
123
126
  command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
124
127
  command
125
128
  end
@@ -250,7 +250,20 @@ module Mongo
250
250
  end
251
251
 
252
252
  def initial_query_op(session)
253
- Operation::MapReduce.new(map_reduce_spec(session))
253
+ spec = map_reduce_spec(session)
254
+ # Read preference isn't simply passed in the command payload
255
+ # (it may need to be converted to wire protocol flags).
256
+ # Passing it in command payload produces errors on at least
257
+ # 5.0 mongoses.
258
+ # In the future map_reduce_command should remove :read
259
+ # from its return value, however we cannot do this right now
260
+ # due to Mongoid 7 relying on :read being returned as part of
261
+ # the command - see RUBY-2932.
262
+ # Delete :read here for now because it cannot be sent to mongos this way.
263
+ spec = spec.dup
264
+ spec[:selector] = spec[:selector].dup
265
+ spec[:selector].delete(:read)
266
+ Operation::MapReduce.new(spec)
254
267
  end
255
268
 
256
269
  def valid_server?(server)
@@ -25,14 +25,31 @@ module Mongo
25
25
  # @api private
26
26
  class KillSpec
27
27
 
28
- def initialize(cursor_id:, coll_name:, db_name:, service_id:)
28
+ def initialize(cursor_id:, coll_name:, db_name:, service_id:, server_address:)
29
29
  @cursor_id = cursor_id
30
30
  @coll_name = coll_name
31
31
  @db_name = db_name
32
32
  @service_id = service_id
33
+ @server_address = server_address
33
34
  end
34
35
 
35
- attr_reader :cursor_id, :coll_name, :db_name, :service_id
36
+ attr_reader :cursor_id, :coll_name, :db_name, :service_id, :server_address
37
+
38
+ def ==(other)
39
+ cursor_id == other.cursor_id &&
40
+ coll_name == other.coll_name &&
41
+ db_name == other.db_name &&
42
+ service_id == other.service_id &&
43
+ server_address == other.server_address
44
+ end
45
+
46
+ def eql?(other)
47
+ self.==(other)
48
+ end
49
+
50
+ def hash
51
+ [cursor_id, coll_name, db_name, service_id, server_address].compact.hash
52
+ end
36
53
  end
37
54
  end
38
55
  end
data/lib/mongo/cursor.rb CHANGED
@@ -84,9 +84,8 @@ module Mongo
84
84
  @session = @options[:session]
85
85
  unless closed?
86
86
  register
87
- ObjectSpace.define_finalizer(self, self.class.finalize(kill_spec,
87
+ ObjectSpace.define_finalizer(self, self.class.finalize(kill_spec(server),
88
88
  cluster,
89
- server,
90
89
  @session))
91
90
  end
92
91
  end
@@ -107,12 +106,12 @@ module Mongo
107
106
  # @return [ Proc ] The Finalizer.
108
107
  #
109
108
  # @api private
110
- def self.finalize(kill_spec, cluster, server, session)
109
+ def self.finalize(kill_spec, cluster, session)
111
110
  unless KillSpec === kill_spec
112
111
  raise ArgumentError, "First argument must be a KillSpec: #{kill_spec.inspect}"
113
112
  end
114
113
  proc do
115
- cluster.schedule_kill_cursor(kill_spec, server)
114
+ cluster.schedule_kill_cursor(kill_spec)
116
115
  session.end_session if session && session.implicit?
117
116
  end
118
117
  end
@@ -367,12 +366,13 @@ module Mongo
367
366
  end
368
367
 
369
368
  # @api private
370
- def kill_spec
369
+ def kill_spec(server)
371
370
  KillSpec.new(
372
371
  cursor_id: id,
373
372
  coll_name: collection_name,
374
373
  db_name: database.name,
375
374
  service_id: initial_result.connection_description.service_id,
375
+ server_address: server.address,
376
376
  )
377
377
  end
378
378
 
data/lib/mongo/version.rb CHANGED
@@ -20,5 +20,5 @@ module Mongo
20
20
  # The current version of the driver.
21
21
  #
22
22
  # @since 2.0.0
23
- VERSION = '2.17.0'.freeze
23
+ VERSION = '2.17.1'.freeze
24
24
  end
@@ -157,6 +157,13 @@ RSpec.configure do |config|
157
157
  end
158
158
 
159
159
  if SpecConfig.instance.active_support?
160
+ require "active_support/version"
161
+ if ActiveSupport.version >= Gem::Version.new(7)
162
+ # ActiveSupport wants us to require ALL of it all of the time.
163
+ # See: https://github.com/rails/rails/issues/43851,
164
+ # https://github.com/rails/rails/issues/43889, etc.
165
+ require 'active_support'
166
+ end
160
167
  require "active_support/time"
161
168
  require 'mongo/active_support'
162
169
  end
@@ -41,12 +41,12 @@ describe Mongo::Cluster::CursorReaper do
41
41
  let(:cursor_id) { 1 }
42
42
  let(:cursor_kill_spec_1) do
43
43
  Mongo::Cursor::KillSpec.new(
44
- cursor_id: cursor_id, coll_name: 'c', db_name: 'd', service_id: nil,
44
+ cursor_id: cursor_id, coll_name: 'c', db_name: 'd', service_id: nil, server_address: address
45
45
  )
46
46
  end
47
47
  let(:cursor_kill_spec_2) do
48
48
  Mongo::Cursor::KillSpec.new(
49
- cursor_id: cursor_id, coll_name: 'c', db_name: 'q', service_id: nil,
49
+ cursor_id: cursor_id, coll_name: 'c', db_name: 'q', service_id: nil, server_address: address
50
50
  )
51
51
  end
52
52
  let(:to_kill) { reaper.instance_variable_get(:@to_kill)}
@@ -60,36 +60,40 @@ describe Mongo::Cluster::CursorReaper do
60
60
  context 'when there is not a list already for the server' do
61
61
 
62
62
  before do
63
- reaper.schedule_kill_cursor(cursor_kill_spec_1, server)
63
+ reaper.schedule_kill_cursor(cursor_kill_spec_1)
64
+ reaper.read_scheduled_kill_specs
64
65
  end
65
66
 
66
67
  it 'initializes the list of op specs to a set' do
67
- expect(to_kill.keys).to eq([ address.seed ])
68
- expect(to_kill[address.seed]).to eq(Set.new([cursor_kill_spec_1]))
68
+ expect(to_kill.keys).to eq([ address ])
69
+ expect(to_kill[address]).to contain_exactly(cursor_kill_spec_1)
69
70
  end
70
71
  end
71
72
 
72
73
  context 'when there is a list of ops already for the server' do
73
74
 
74
75
  before do
75
- reaper.schedule_kill_cursor(cursor_kill_spec_1, server)
76
- reaper.schedule_kill_cursor(cursor_kill_spec_2, server)
76
+ reaper.schedule_kill_cursor(cursor_kill_spec_1)
77
+ reaper.read_scheduled_kill_specs
78
+ reaper.schedule_kill_cursor(cursor_kill_spec_2)
79
+ reaper.read_scheduled_kill_specs
77
80
  end
78
81
 
79
82
  it 'adds the op to the server list' do
80
- expect(to_kill.keys).to eq([ address.seed ])
81
- expect(to_kill[address.seed]).to contain_exactly(cursor_kill_spec_1, cursor_kill_spec_2)
83
+ expect(to_kill.keys).to eq([ address ])
84
+ expect(to_kill[address]).to contain_exactly(cursor_kill_spec_1, cursor_kill_spec_2)
82
85
  end
83
86
 
84
87
  context 'when the same op is added more than once' do
85
88
 
86
89
  before do
87
- reaper.schedule_kill_cursor(cursor_kill_spec_2, server)
90
+ reaper.schedule_kill_cursor(cursor_kill_spec_2)
91
+ reaper.read_scheduled_kill_specs
88
92
  end
89
93
 
90
94
  it 'does not allow duplicates ops for a server' do
91
- expect(to_kill.keys).to eq([ address.seed ])
92
- expect(to_kill[address.seed]).to contain_exactly(cursor_kill_spec_1, cursor_kill_spec_2)
95
+ expect(to_kill.keys).to eq([ address ])
96
+ expect(to_kill[address]).to contain_exactly(cursor_kill_spec_1, cursor_kill_spec_2)
93
97
  end
94
98
  end
95
99
  end
@@ -98,7 +102,7 @@ describe Mongo::Cluster::CursorReaper do
98
102
  context 'when the cursor is not on the list of active cursors' do
99
103
 
100
104
  before do
101
- reaper.schedule_kill_cursor(cursor_kill_spec_1, server)
105
+ reaper.schedule_kill_cursor(cursor_kill_spec_1)
102
106
  end
103
107
 
104
108
  it 'does not add the kill cursors op spec to the list' do
@@ -189,8 +193,11 @@ describe Mongo::Cluster::CursorReaper do
189
193
  around do |example|
190
194
  authorized_collection.insert_many(docs)
191
195
  periodic_executor.stop!
192
- cluster.schedule_kill_cursor(cursor.kill_spec,
193
- cursor.instance_variable_get(:@server))
196
+ cluster.schedule_kill_cursor(
197
+ cursor.kill_spec(
198
+ cursor.instance_variable_get(:@server)
199
+ )
200
+ )
194
201
  periodic_executor.flush
195
202
  example.run
196
203
  periodic_executor.run!
@@ -878,4 +878,20 @@ describe Mongo::Collection::View::MapReduce do
878
878
  end
879
879
  end
880
880
  end
881
+
882
+ describe '#map_reduce_spec' do
883
+ context 'when read preference is given' do
884
+ let(:view_options) do
885
+ { read: {mode: :secondary} }
886
+ end
887
+
888
+ context 'selector' do
889
+ # For compatibility with released versions of Mongoid, this method
890
+ # must return read preference under the :read key.
891
+ it 'contains read preference' do
892
+ map_reduce_spec[:selector][:read].should == {'mode' => :secondary}
893
+ end
894
+ end
895
+ end
896
+ end
881
897
  end
@@ -331,8 +331,9 @@ describe Mongo::Cursor do
331
331
 
332
332
  before do
333
333
  authorized_collection.insert_many(documents)
334
- cluster.schedule_kill_cursor(cursor.kill_spec,
335
- cursor.instance_variable_get(:@server))
334
+ cluster.schedule_kill_cursor(
335
+ cursor.kill_spec(cursor.instance_variable_get(:@server))
336
+ )
336
337
  end
337
338
 
338
339
  let(:view) do
data/spec/runners/auth.rb CHANGED
@@ -48,7 +48,7 @@ module Mongo
48
48
  attr_reader :tests
49
49
 
50
50
  def initialize(test_path)
51
- @spec = YAML.load(File.read(test_path))
51
+ @spec = ::Utils.load_spec_yaml_file(test_path)
52
52
  @description = File.basename(test_path)
53
53
  end
54
54
 
@@ -32,7 +32,7 @@ module Mongo
32
32
  #
33
33
  # @since 2.6.0
34
34
  def initialize(test_path)
35
- @spec = YAML.load(File.read(test_path))
35
+ @spec = ::Utils.load_spec_yaml_file(test_path)
36
36
  @description = File.basename(test_path)
37
37
  @spec_tests = @spec['tests']
38
38
  @collection_name = @spec['collection_name']
data/spec/runners/cmap.rb CHANGED
@@ -40,7 +40,7 @@ module Mongo
40
40
  #
41
41
  # @param [ String ] test_path The path to the file.
42
42
  def initialize(test_path)
43
- @test = YAML.load(File.read(test_path))
43
+ @test = ::Utils.load_spec_yaml_file(test_path)
44
44
 
45
45
  @description = @test['description']
46
46
  @pool_options = ::Utils.snakeize_hash(process_options(@test['poolOptions']))
@@ -204,7 +204,7 @@ module Mongo
204
204
  #
205
205
  # @since 2.1.0
206
206
  def initialize(test_path)
207
- @spec = YAML.load(File.read(test_path))
207
+ @spec = ::Utils.load_spec_yaml_file(test_path)
208
208
  @data = @spec['data']
209
209
  @tests = @spec['tests']
210
210
  end
@@ -100,7 +100,7 @@ module Mongo
100
100
  #
101
101
  # @since 2.0.0
102
102
  def initialize(test_path)
103
- @spec = YAML.load(File.read(test_path))
103
+ @spec = ::Utils.load_spec_yaml_file(test_path)
104
104
  @description = File.basename(test_path)
105
105
  end
106
106
 
@@ -12,9 +12,7 @@ module Mongo
12
12
  #
13
13
  # @since 2.0.0
14
14
  def initialize(test_path)
15
- contents = File.read(test_path)
16
-
17
- @spec = YAML.load(contents)
15
+ @spec = ::Utils.load_spec_yaml_file(test_path)
18
16
  @description = File.basename(test_path)
19
17
  @data = BSON::ExtJSON.parse_obj(@spec['data'])
20
18
  @tests = @spec['tests']
@@ -100,7 +100,7 @@ module Mongo
100
100
  #
101
101
  # @since 2.1.0
102
102
  def initialize(test_path)
103
- @spec = YAML.load(File.read(test_path))
103
+ @spec = ::Utils.load_spec_yaml_file(test_path)
104
104
  @description = File.basename(test_path)
105
105
  @data = @spec['data']
106
106
  end
@@ -13,7 +13,7 @@ module ReadWriteConcernDocument
13
13
  #
14
14
  # @since 2.0.0
15
15
  def initialize(test_path)
16
- @spec = YAML.load(File.read(test_path))
16
+ @spec = ::Utils.load_spec_yaml_file(test_path)
17
17
  @description = File.basename(test_path)
18
18
  end
19
19
 
data/spec/runners/sdam.rb CHANGED
@@ -77,7 +77,7 @@ module Mongo
77
77
  #
78
78
  # @since 2.0.0
79
79
  def initialize(test_path)
80
- @test = YAML.load(File.read(test_path))
80
+ @test = ::Utils.load_spec_yaml_file(test_path)
81
81
  @description = @test['description']
82
82
  @uri_string = @test['uri']
83
83
  @uri = URI.new(uri_string)
@@ -64,7 +64,7 @@ module Mongo
64
64
  #
65
65
  # @since 2.0.0
66
66
  def initialize(test_path)
67
- @test = YAML.load(File.read(test_path))
67
+ @test = ::Utils.load_spec_yaml_file(test_path)
68
68
  @description = "#{@test['topology_description']['type']}: #{File.basename(test_path)}"
69
69
  @heartbeat_frequency = @test['heartbeatFrequencyMS'] / 1000 if @test['heartbeatFrequencyMS']
70
70
  @read_preference = @test['read_preference']
@@ -28,7 +28,7 @@ module Mongo
28
28
  #
29
29
  # @since 2.0.0
30
30
  def initialize(test_path)
31
- @test = YAML.load(File.read(test_path))
31
+ @test = ::Utils.load_spec_yaml_file(test_path)
32
32
  @description = "#{File.basename(test_path)}: avg_rtt_ms: #{@test['avg_rtt_ms']}, new_rtt_ms: #{@test['new_rtt_ms']}," +
33
33
  " new_avg_rtt: #{@test['new_avg_rtt']}"
34
34
  @average_rtt = @test['avg_rtt_ms'] == 'NULL' ? nil : @test['avg_rtt_ms'].to_f / 1000
@@ -6,7 +6,7 @@ module Unified
6
6
  class TestGroup
7
7
  def initialize(path, **opts)
8
8
  if String === path
9
- data = YAML.load(File.read(path))
9
+ data = ::Utils.load_spec_yaml_file(path)
10
10
  else
11
11
  data = path
12
12
  end
@@ -15,7 +15,7 @@ describe 'DNS Seedlist Discovery' do
15
15
 
16
16
  SEED_LIST_DISCOVERY_TESTS.each do |test_path|
17
17
 
18
- spec = YAML.load(File.read(test_path))
18
+ spec = ::Utils.load_spec_yaml_file(test_path)
19
19
 
20
20
  test = Mongo::ConnectionString::Test.new(spec)
21
21
 
@@ -595,4 +595,35 @@ module Utils
595
595
  end
596
596
  end
597
597
  end
598
+
599
+ module_function def load_spec_yaml_file(path)
600
+ permitted_classes = [
601
+ BigDecimal,
602
+ Date,
603
+ Time,
604
+ Range,
605
+ Regexp,
606
+ Symbol,
607
+ BSON::Binary,
608
+ BSON::Code,
609
+ BSON::CodeWithScope,
610
+ BSON::DbPointer,
611
+ BSON::Decimal128,
612
+ BSON::Int32,
613
+ BSON::Int64,
614
+ BSON::MaxKey,
615
+ BSON::MinKey,
616
+ BSON::ObjectId,
617
+ BSON::Regexp::Raw,
618
+ BSON::Symbol::Raw,
619
+ BSON::Timestamp,
620
+ BSON::Undefined,
621
+ ]
622
+ if RUBY_VERSION.start_with?("2.5")
623
+ YAML.safe_load(File.read(path), permitted_classes, [], true)
624
+ else
625
+ # Here we have Ruby 2.6+ that supports the new syntax of `safe_load``.
626
+ YAML.safe_load(File.read(path), permitted_classes: permitted_classes, aliases: true)
627
+ end
628
+ end
598
629
  end
data.tar.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- R��NE��u3��o�|�M���:ٻ�5C��KI��9n��LF��k���xѻ���� �Jd�m�R̺vG�g�V�>��������3h�����1��S�`���d��AlA��E�K+{��UX��6\�tۚ˅L ]ʘ��%�&�6u�б��������L��V���rU��d��V]�$R��19�Y�7v��o��FI��m
2
- YkuШ���;��^���h�ǐ멾���n�=�/
1
+ �1�o5
2
+ q��7� ������t��A!m�Ks�w�_��2�/���@C�� �T��E�rX6��*b�J���9�� �ʲRQʨ:�D_�6��'fz�6����ް
3
+ ��jN:ɳ9Ͽ@��H4ga@�=�|��"� �W|�h��BH�\
4
+ ���W���,jsgb ���c�HnT.�2 ]�f��T�`�"��I�&�@�^���9���1<5������|N�f����坋��