mongo 2.13.0.beta1 → 2.13.0.rc1

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.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -5
  4. data/Rakefile +15 -9
  5. data/lib/mongo.rb +4 -2
  6. data/lib/mongo/auth/aws/request.rb +4 -2
  7. data/lib/mongo/bulk_write.rb +1 -0
  8. data/lib/mongo/client.rb +143 -21
  9. data/lib/mongo/cluster.rb +53 -17
  10. data/lib/mongo/cluster/sdam_flow.rb +13 -10
  11. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +3 -2
  12. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  13. data/lib/mongo/cluster/topology/single.rb +1 -1
  14. data/lib/mongo/collection.rb +17 -13
  15. data/lib/mongo/collection/view/readable.rb +3 -1
  16. data/lib/mongo/collection/view/writable.rb +41 -5
  17. data/lib/mongo/database.rb +31 -4
  18. data/lib/mongo/database/view.rb +19 -4
  19. data/lib/mongo/distinguishing_semaphore.rb +55 -0
  20. data/lib/mongo/error.rb +1 -0
  21. data/lib/mongo/error/invalid_session.rb +2 -1
  22. data/lib/mongo/error/operation_failure.rb +6 -0
  23. data/lib/mongo/error/sessions_not_supported.rb +35 -0
  24. data/lib/mongo/event/base.rb +6 -0
  25. data/lib/mongo/grid/file.rb +5 -0
  26. data/lib/mongo/grid/file/chunk.rb +2 -0
  27. data/lib/mongo/grid/fs_bucket.rb +15 -13
  28. data/lib/mongo/grid/stream/write.rb +9 -3
  29. data/lib/mongo/monitoring.rb +38 -0
  30. data/lib/mongo/monitoring/command_log_subscriber.rb +10 -2
  31. data/lib/mongo/monitoring/event/command_failed.rb +11 -0
  32. data/lib/mongo/monitoring/event/command_started.rb +37 -2
  33. data/lib/mongo/monitoring/event/command_succeeded.rb +11 -0
  34. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  35. data/lib/mongo/monitoring/event/server_description_changed.rb +27 -4
  36. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +9 -2
  37. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +9 -2
  38. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +9 -2
  39. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  40. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  41. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  42. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  43. data/lib/mongo/monitoring/publishable.rb +6 -3
  44. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +9 -1
  45. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  46. data/lib/mongo/protocol/message.rb +36 -8
  47. data/lib/mongo/protocol/msg.rb +14 -0
  48. data/lib/mongo/protocol/serializers.rb +5 -2
  49. data/lib/mongo/server.rb +10 -3
  50. data/lib/mongo/server/connection.rb +4 -4
  51. data/lib/mongo/server/connection_base.rb +3 -1
  52. data/lib/mongo/server/description.rb +5 -0
  53. data/lib/mongo/server/monitor.rb +76 -44
  54. data/lib/mongo/server/monitor/connection.rb +55 -7
  55. data/lib/mongo/server/pending_connection.rb +14 -4
  56. data/lib/mongo/server/push_monitor.rb +173 -0
  57. data/{spec/runners/transactions/context.rb → lib/mongo/server/push_monitor/connection.rb} +9 -14
  58. data/lib/mongo/server_selector.rb +0 -1
  59. data/lib/mongo/server_selector/base.rb +579 -1
  60. data/lib/mongo/server_selector/nearest.rb +1 -6
  61. data/lib/mongo/server_selector/primary.rb +1 -6
  62. data/lib/mongo/server_selector/primary_preferred.rb +7 -10
  63. data/lib/mongo/server_selector/secondary.rb +1 -6
  64. data/lib/mongo/server_selector/secondary_preferred.rb +1 -7
  65. data/lib/mongo/session.rb +2 -0
  66. data/lib/mongo/socket.rb +20 -8
  67. data/lib/mongo/socket/ssl.rb +1 -1
  68. data/lib/mongo/socket/tcp.rb +1 -1
  69. data/lib/mongo/topology_version.rb +9 -0
  70. data/lib/mongo/utils.rb +62 -0
  71. data/lib/mongo/version.rb +1 -1
  72. data/spec/README.aws-auth.md +2 -2
  73. data/spec/integration/awaited_ismaster_spec.rb +28 -0
  74. data/spec/integration/change_stream_examples_spec.rb +6 -2
  75. data/spec/integration/check_clean_slate_spec.rb +16 -0
  76. data/spec/integration/client_construction_spec.rb +1 -0
  77. data/spec/integration/connect_single_rs_name_spec.rb +5 -2
  78. data/spec/integration/connection_spec.rb +7 -4
  79. data/spec/integration/crud_spec.rb +4 -4
  80. data/spec/integration/docs_examples_spec.rb +6 -0
  81. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  82. data/spec/integration/heartbeat_events_spec.rb +4 -23
  83. data/spec/integration/read_concern_spec.rb +1 -1
  84. data/spec/integration/retryable_errors_spec.rb +1 -1
  85. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -2
  86. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +3 -3
  87. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +2 -2
  88. data/spec/integration/sdam_error_handling_spec.rb +37 -15
  89. data/spec/integration/sdam_events_spec.rb +77 -6
  90. data/spec/integration/sdam_prose_spec.rb +64 -0
  91. data/spec/integration/server_monitor_spec.rb +25 -1
  92. data/spec/integration/size_limit_spec.rb +7 -3
  93. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +98 -0
  94. data/spec/integration/ssl_uri_options_spec.rb +2 -2
  95. data/spec/integration/zlib_compression_spec.rb +25 -0
  96. data/spec/lite_spec_helper.rb +12 -5
  97. data/spec/mongo/auth/aws/request_spec.rb +76 -0
  98. data/spec/mongo/auth/scram_spec.rb +1 -1
  99. data/spec/mongo/client_construction_spec.rb +207 -0
  100. data/spec/mongo/client_spec.rb +38 -3
  101. data/spec/mongo/cluster/topology/replica_set_spec.rb +52 -9
  102. data/spec/mongo/cluster/topology/single_spec.rb +4 -2
  103. data/spec/mongo/cluster_spec.rb +34 -35
  104. data/spec/mongo/collection/view/change_stream_resume_spec.rb +6 -6
  105. data/spec/mongo/collection_spec.rb +500 -0
  106. data/spec/mongo/database_spec.rb +245 -8
  107. data/spec/mongo/distinguishing_semaphore_spec.rb +63 -0
  108. data/spec/mongo/error/operation_failure_spec.rb +40 -0
  109. data/spec/mongo/index/view_spec.rb +2 -2
  110. data/spec/mongo/monitoring/event/server_description_changed_spec.rb +1 -4
  111. data/spec/mongo/protocol/msg_spec.rb +10 -0
  112. data/spec/mongo/semaphore_spec.rb +51 -0
  113. data/spec/mongo/server/connection_auth_spec.rb +2 -2
  114. data/spec/mongo/server_selector/nearest_spec.rb +23 -23
  115. data/spec/mongo/server_selector/primary_preferred_spec.rb +26 -26
  116. data/spec/mongo/server_selector/primary_spec.rb +9 -9
  117. data/spec/mongo/server_selector/secondary_preferred_spec.rb +22 -22
  118. data/spec/mongo/server_selector/secondary_spec.rb +18 -18
  119. data/spec/mongo/server_selector_spec.rb +4 -4
  120. data/spec/mongo/session_spec.rb +35 -0
  121. data/spec/runners/change_streams/test.rb +2 -2
  122. data/spec/runners/cmap.rb +1 -1
  123. data/spec/runners/command_monitoring.rb +3 -34
  124. data/spec/runners/crud/context.rb +9 -5
  125. data/spec/runners/crud/operation.rb +59 -27
  126. data/spec/runners/crud/spec.rb +0 -8
  127. data/spec/runners/crud/test.rb +1 -1
  128. data/spec/runners/sdam.rb +2 -2
  129. data/spec/runners/server_selection.rb +242 -28
  130. data/spec/runners/transactions.rb +12 -12
  131. data/spec/runners/transactions/operation.rb +151 -25
  132. data/spec/runners/transactions/test.rb +60 -16
  133. data/spec/spec_tests/command_monitoring_spec.rb +22 -12
  134. data/spec/spec_tests/crud_spec.rb +1 -1
  135. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +4 -8
  136. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +66 -0
  137. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.yml +15 -0
  138. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/NoKnownServers.yml +4 -3
  139. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -0
  140. data/spec/spec_tests/data/sdam_integration/cancel-server-check.yml +96 -0
  141. data/spec/spec_tests/data/sdam_integration/connectTimeoutMS.yml +88 -0
  142. data/spec/spec_tests/data/sdam_integration/find-network-error.yml +83 -0
  143. data/spec/spec_tests/data/sdam_integration/find-shutdown-error.yml +116 -0
  144. data/spec/spec_tests/data/sdam_integration/insert-network-error.yml +86 -0
  145. data/spec/spec_tests/data/sdam_integration/insert-shutdown-error.yml +115 -0
  146. data/spec/spec_tests/data/sdam_integration/isMaster-command-error.yml +168 -0
  147. data/spec/spec_tests/data/sdam_integration/isMaster-network-error.yml +162 -0
  148. data/spec/spec_tests/data/sdam_integration/isMaster-timeout.yml +229 -0
  149. data/spec/spec_tests/data/sdam_integration/rediscover-quickly-after-step-down.yml +87 -0
  150. data/spec/spec_tests/max_staleness_spec.rb +4 -142
  151. data/spec/spec_tests/retryable_reads_spec.rb +2 -2
  152. data/spec/spec_tests/sdam_integration_spec.rb +13 -0
  153. data/spec/spec_tests/sdam_monitoring_spec.rb +1 -2
  154. data/spec/spec_tests/server_selection_spec.rb +4 -116
  155. data/spec/stress/cleanup_spec.rb +17 -2
  156. data/spec/stress/connection_pool_stress_spec.rb +10 -8
  157. data/spec/support/child_process_helper.rb +78 -0
  158. data/spec/support/client_registry.rb +1 -0
  159. data/spec/support/cluster_config.rb +4 -0
  160. data/spec/support/event_subscriber.rb +123 -33
  161. data/spec/support/keyword_struct.rb +26 -0
  162. data/spec/support/shared/server_selector.rb +13 -1
  163. data/spec/support/spec_config.rb +38 -13
  164. data/spec/support/spec_organizer.rb +129 -0
  165. data/spec/support/spec_setup.rb +1 -1
  166. data/spec/support/utils.rb +46 -0
  167. metadata +992 -942
  168. metadata.gz.sig +0 -0
  169. data/lib/mongo/server_selector/selectable.rb +0 -560
  170. data/spec/runners/sdam_monitoring.rb +0 -89
@@ -25,12 +25,13 @@ class Mongo::Cluster
25
25
  class SdamFlow
26
26
  extend Forwardable
27
27
 
28
- def initialize(cluster, previous_desc, updated_desc)
28
+ def initialize(cluster, previous_desc, updated_desc, awaited: false)
29
29
  @cluster = cluster
30
30
  @topology = cluster.topology
31
31
  @original_desc = @previous_desc = previous_desc
32
32
  @updated_desc = updated_desc
33
33
  @servers_to_disconnect = []
34
+ @awaited = !!awaited
34
35
  end
35
36
 
36
37
  attr_reader :cluster
@@ -51,6 +52,10 @@ class Mongo::Cluster
51
52
  attr_reader :updated_desc
52
53
  attr_reader :original_desc
53
54
 
55
+ def awaited?
56
+ @awaited
57
+ end
58
+
54
59
  def_delegators :topology, :replica_set_name
55
60
 
56
61
  # Updates descriptions on all servers whose address matches
@@ -431,15 +436,12 @@ class Mongo::Cluster
431
436
  # the server - in case of a stale primary, the server reported itself
432
437
  # as being a primary but updated_desc here will be unknown.
433
438
 
434
- # We do not notify on unknown -> unknown changes.
435
- # This can also be important for tests which have real i/o
436
- # happening against bogus addresses which yield unknown responses
437
- # and that also mock responses with the resulting race condition,
438
- # though tests should avoid performing real i/o with monitoring_io: false
439
- # option.
440
- if updated_desc.unknown? && previous_desc.unknown?
441
- return
442
- end
439
+ # We used to not notify on Unknown -> Unknown server changes.
440
+ # Technically these are valid state changes (or at least as valid as
441
+ # other server description changes when the description has not
442
+ # changed meaningfully but the events are still published).
443
+ # The current version of the driver notifies on Unknown -> Unknown
444
+ # transitions.
443
445
 
444
446
  # Avoid dispatching events when updated description is the same as
445
447
  # previous description. This allows this method to be called multiple
@@ -456,6 +458,7 @@ class Mongo::Cluster
456
458
  topology,
457
459
  previous_desc,
458
460
  updated_desc,
461
+ awaited: awaited?,
459
462
  )
460
463
  )
461
464
  @previous_desc = updated_desc
@@ -73,8 +73,9 @@ module Mongo
73
73
  # @return [ true, false ] If a readable server is present.
74
74
  #
75
75
  # @since 2.4.0
76
+ # @deprecated
76
77
  def has_readable_server?(cluster, server_selector = nil)
77
- (server_selector || ServerSelector.primary).candidates(cluster).any?
78
+ !(server_selector || ServerSelector.primary).try_select_server(cluster).nil?
78
79
  end
79
80
 
80
81
  # Determine if the topology would select a writable server for the
@@ -89,7 +90,7 @@ module Mongo
89
90
  #
90
91
  # @since 2.4.0
91
92
  def has_writable_server?(cluster)
92
- cluster.servers.any?{ |server| server.primary? }
93
+ !ServerSelector.primary.try_select_server(cluster).nil?
93
94
  end
94
95
 
95
96
  # A replica set topology is a replica set.
@@ -97,7 +97,7 @@ module Mongo
97
97
  #
98
98
  # @since 2.0.0
99
99
  def servers(servers)
100
- servers.select{ |server| server.mongos? }
100
+ servers.select { |server| server.mongos? }
101
101
  end
102
102
 
103
103
  # A sharded topology is sharded.
@@ -96,7 +96,7 @@ module Mongo
96
96
  #
97
97
  # @since 2.0.0
98
98
  def servers(servers, name = nil)
99
- [ servers.detect { |server| !server.unknown? } ]
99
+ servers.reject { |server| server.unknown? }
100
100
  end
101
101
 
102
102
  # A single topology is not sharded.
@@ -429,7 +429,7 @@ module Mongo
429
429
  View.new(self, filter || {}, options).count(options)
430
430
  end
431
431
 
432
- # Gets the number of of matching documents in the collection. Unlike the deprecated #count
432
+ # Gets the number of matching documents in the collection. Unlike the deprecated #count
433
433
  # method, this will return the exact number of documents matching the filter rather than the estimate.
434
434
  #
435
435
  # @example Get the number of documents in the collection.
@@ -450,7 +450,7 @@ module Mongo
450
450
  # @return [ Integer ] The document count.
451
451
  #
452
452
  # @since 2.6.0
453
- def count_documents(filter, options = {})
453
+ def count_documents(filter = {}, options = {})
454
454
  View.new(self, filter, options).count_documents(options)
455
455
  end
456
456
 
@@ -537,19 +537,23 @@ module Mongo
537
537
  # @since 2.0.0
538
538
  def insert_one(document, opts = {})
539
539
  client.send(:with_session, opts) do |session|
540
- write_concern = write_concern_with_session(session)
540
+ write_concern = if opts[:write_concern]
541
+ WriteConcern.get(opts[:write_concern])
542
+ else
543
+ write_concern_with_session(session)
544
+ end
541
545
  write_with_retry(session, write_concern) do |server, txn_num|
542
546
  Operation::Insert.new(
543
- :documents => [ document ],
544
- :db_name => database.name,
545
- :coll_name => name,
546
- :write_concern => write_concern,
547
- :bypass_document_validation => !!opts[:bypass_document_validation],
548
- :options => opts,
549
- :id_generator => client.options[:id_generator],
550
- :session => session,
551
- :txn_num => txn_num
552
- ).execute(server, client: client)
547
+ :documents => [ document ],
548
+ :db_name => database.name,
549
+ :coll_name => name,
550
+ :write_concern => write_concern,
551
+ :bypass_document_validation => !!opts[:bypass_document_validation],
552
+ :options => opts,
553
+ :id_generator => client.options[:id_generator],
554
+ :session => session,
555
+ :txn_num => txn_num
556
+ ).execute(server, client: client)
553
557
  end
554
558
  end
555
559
  end
@@ -193,7 +193,9 @@ module Mongo
193
193
  pipeline << { :'$limit' => opts[:limit] } if opts[:limit]
194
194
  pipeline << { :'$group' => { _id: 1, n: { :'$sum' => 1 } } }
195
195
 
196
- opts.select! { |k, _| [:hint, :max_time_ms, :read, :collation, :session].include?(k) }
196
+ opts = opts.select { |k, _| [:hint, :max_time_ms, :read, :collation, :session].include?(k) }
197
+ opts[:collation] ||= collation
198
+
197
199
  first = aggregate(pipeline, opts).first
198
200
  return 0 unless first
199
201
  first['n'].to_i
@@ -52,6 +52,9 @@ module Mongo
52
52
  cmd[:fields] = projection if projection
53
53
  cmd[:sort] = sort if sort
54
54
  cmd[:maxTimeMS] = max_time_ms if max_time_ms
55
+ if opts[:bypass_document_validation]
56
+ cmd[:bypassDocumentValidation] = true
57
+ end
55
58
 
56
59
  with_session(opts) do |session|
57
60
  applied_write_concern = applied_write_concern(session)
@@ -165,6 +168,8 @@ module Mongo
165
168
  # @option opts [ Session ] :session The session to use.
166
169
  # @option opts [ Hash | String ] :hint The index to use for this operation.
167
170
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
171
+ # @option opts [ Hash ] :write_concern The write concern options.
172
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
168
173
  #
169
174
  # @return [ Result ] The response from the database.
170
175
  #
@@ -172,7 +177,11 @@ module Mongo
172
177
  def delete_many(opts = {})
173
178
  delete_doc = { Operation::Q => filter, Operation::LIMIT => 0 }
174
179
  with_session(opts) do |session|
175
- write_concern = write_concern_with_session(session)
180
+ write_concern = if opts[:write_concern]
181
+ WriteConcern.get(opts[:write_concern])
182
+ else
183
+ write_concern_with_session(session)
184
+ end
176
185
  nro_write_with_retry(session, write_concern) do |server|
177
186
  apply_collation!(delete_doc, server, opts)
178
187
  apply_hint!(delete_doc, server, opts.merge(write_concern: write_concern))
@@ -182,6 +191,7 @@ module Mongo
182
191
  :db_name => collection.database.name,
183
192
  :coll_name => collection.name,
184
193
  :write_concern => write_concern,
194
+ :bypass_document_validation => !!opts[:bypass_document_validation],
185
195
  :session => session
186
196
  ).execute(server, client: client)
187
197
  end
@@ -199,6 +209,8 @@ module Mongo
199
209
  # @option opts [ Session ] :session The session to use.
200
210
  # @option opts [ Hash | String ] :hint The index to use for this operation.
201
211
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
212
+ # @option opts [ Hash ] :write_concern The write concern options.
213
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
202
214
  #
203
215
  # @return [ Result ] The response from the database.
204
216
  #
@@ -206,7 +218,11 @@ module Mongo
206
218
  def delete_one(opts = {})
207
219
  delete_doc = { Operation::Q => filter, Operation::LIMIT => 1 }
208
220
  with_session(opts) do |session|
209
- write_concern = write_concern_with_session(session)
221
+ write_concern = if opts[:write_concern]
222
+ WriteConcern.get(opts[:write_concern])
223
+ else
224
+ write_concern_with_session(session)
225
+ end
210
226
  write_with_retry(session, write_concern) do |server, txn_num|
211
227
  apply_collation!(delete_doc, server, opts)
212
228
  apply_hint!(delete_doc, server, opts.merge(write_concern: write_concern))
@@ -216,6 +232,7 @@ module Mongo
216
232
  :db_name => collection.database.name,
217
233
  :coll_name => collection.name,
218
234
  :write_concern => write_concern,
235
+ :bypass_document_validation => !!opts[:bypass_document_validation],
219
236
  :session => session,
220
237
  :txn_num => txn_num
221
238
  ).execute(server, client: client)
@@ -239,6 +256,8 @@ module Mongo
239
256
  # @option opts [ Session ] :session The session to use.
240
257
  # @option opts [ Hash | String ] :hint The index to use for this operation.
241
258
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
259
+ # @option opts [ Hash ] :write_concern The write concern options.
260
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
242
261
  #
243
262
  # @return [ Result ] The response from the database.
244
263
  #
@@ -251,7 +270,12 @@ module Mongo
251
270
  update_doc['upsert'] = true
252
271
  end
253
272
  with_session(opts) do |session|
254
- write_concern = write_concern_with_session(session)
273
+ write_concern = if opts[:write_concern]
274
+ WriteConcern.get(opts[:write_concern])
275
+ else
276
+ write_concern_with_session(session)
277
+ end
278
+
255
279
  write_with_retry(session, write_concern) do |server, txn_num|
256
280
  apply_collation!(update_doc, server, opts)
257
281
  apply_array_filters!(update_doc, server, opts)
@@ -288,6 +312,8 @@ module Mongo
288
312
  # @option opts [ Session ] :session The session to use.
289
313
  # @option opts [ Hash | String ] :hint The index to use for this operation.
290
314
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
315
+ # @option opts [ Hash ] :write_concern The write concern options.
316
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
291
317
  #
292
318
  # @return [ Result ] The response from the database.
293
319
  #
@@ -301,7 +327,11 @@ module Mongo
301
327
  update_doc['upsert'] = true
302
328
  end
303
329
  with_session(opts) do |session|
304
- write_concern = write_concern_with_session(session)
330
+ write_concern = if opts[:write_concern]
331
+ WriteConcern.get(opts[:write_concern])
332
+ else
333
+ write_concern_with_session(session)
334
+ end
305
335
  nro_write_with_retry(session, write_concern) do |server|
306
336
  apply_collation!(update_doc, server, opts)
307
337
  apply_array_filters!(update_doc, server, opts)
@@ -337,6 +367,8 @@ module Mongo
337
367
  # @option opts [ Session ] :session The session to use.
338
368
  # @option opts [ Hash | String ] :hint The index to use for this operation.
339
369
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
370
+ # @option opts [ Hash ] :write_concern The write concern options.
371
+ # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
340
372
  #
341
373
  # @return [ Result ] The response from the database.
342
374
  #
@@ -349,7 +381,11 @@ module Mongo
349
381
  update_doc['upsert'] = true
350
382
  end
351
383
  with_session(opts) do |session|
352
- write_concern = write_concern_with_session(session)
384
+ write_concern = if opts[:write_concern]
385
+ WriteConcern.get(opts[:write_concern])
386
+ else
387
+ write_concern_with_session(session)
388
+ end
353
389
  write_with_retry(session, write_concern) do |server, txn_num|
354
390
  apply_collation!(update_doc, server, opts)
355
391
  apply_array_filters!(update_doc, server, opts)
@@ -113,6 +113,16 @@ module Mongo
113
113
  # @note The set of returned collection names depends on the version of
114
114
  # MongoDB server that fulfills the request.
115
115
  #
116
+ # @param [ Hash ] options
117
+ #
118
+ # @option options [ Hash ] :filter A filter on the collections returned.
119
+ # @option options [ true, false ] :authorized_collections A flag, when
120
+ # set to true and used with nameOnly: true, that allows a user without the
121
+ # required privilege to run the command when access control is enforced
122
+ #
123
+ # See https://docs.mongodb.com/manual/reference/command/listCollections/
124
+ # for more information and usage.
125
+ #
116
126
  # @return [ Array<String> ] Names of the collections.
117
127
  #
118
128
  # @since 2.0.0
@@ -129,6 +139,13 @@ module Mongo
129
139
  # @param [ Hash ] options
130
140
  #
131
141
  # @option options [ Hash ] :filter A filter on the collections returned.
142
+ # @option options [ true, false ] :name_only Indicates whether command
143
+ # should return just collection/view names and type or return both the
144
+ # name and other information
145
+ # @option options [ true, false ] :authorized_collections A flag, when
146
+ # set to true and used with nameOnly: true, that allows a user without the
147
+ # required privilege to run the command when access control is enforced
148
+ #
132
149
  # See https://docs.mongodb.com/manual/reference/command/listCollections/
133
150
  # for more information and usage.
134
151
  #
@@ -136,8 +153,8 @@ module Mongo
136
153
  # collection in the database.
137
154
  #
138
155
  # @since 2.0.5
139
- def list_collections(**options)
140
- View.new(self).list_collections(**options)
156
+ def list_collections(options = {})
157
+ View.new(self).list_collections(options)
141
158
  end
142
159
 
143
160
  # Get all the non-system collections that belong to this database.
@@ -145,11 +162,21 @@ module Mongo
145
162
  # @note The set of returned collections depends on the version of
146
163
  # MongoDB server that fulfills the request.
147
164
  #
165
+ # @param [ Hash ] options
166
+ #
167
+ # @option options [ Hash ] :filter A filter on the collections returned.
168
+ # @option options [ true, false ] :authorized_collections A flag, when
169
+ # set to true and used with name_only: true, that allows a user without the
170
+ # required privilege to run the command when access control is enforced
171
+ #
172
+ # See https://docs.mongodb.com/manual/reference/command/listCollections/
173
+ # for more information and usage.
174
+ #
148
175
  # @return [ Array<Mongo::Collection> ] The collections.
149
176
  #
150
177
  # @since 2.0.0
151
- def collections
152
- collection_names.map { |name| collection(name) }
178
+ def collections(options = {})
179
+ collection_names(options).map { |name| collection(name) }
153
180
  end
154
181
 
155
182
  # Execute a command on the database.
@@ -47,6 +47,13 @@ module Mongo
47
47
  #
48
48
  # @option options [ Integer ] :batch_size The batch size for results
49
49
  # returned from the listCollections command.
50
+ # @option options [ Hash ] :filter A filter on the collections returned.
51
+ # @option options [ true, false ] :authorized_collections A flag, when
52
+ # set to true, that allows a user without the required privilege
53
+ # to run the command when access control is enforced
54
+ #
55
+ # See https://docs.mongodb.com/manual/reference/command/listCollections/
56
+ # for more information and usage.
50
57
  #
51
58
  # @return [ Array<String> ] The names of all non-system collections.
52
59
  #
@@ -55,7 +62,7 @@ module Mongo
55
62
  @batch_size = options[:batch_size]
56
63
  session = client.send(:get_session, options)
57
64
  cursor = read_with_retry_cursor(session, ServerSelector.primary, self) do |server|
58
- send_initial_query(server, session, name_only: true)
65
+ send_initial_query(server, session, options.merge(name_only: true))
59
66
  end
60
67
  cursor.map do |info|
61
68
  if cursor.server.with_connection { |connection| connection.features }.list_collections_enabled?
@@ -81,15 +88,22 @@ module Mongo
81
88
  # @param [ Hash ] options
82
89
  #
83
90
  # @option options [ Hash ] :filter A filter on the collections returned.
91
+ # @option options [ true, false ] :name_only Indicates whether command
92
+ # should return just collection/view names and type or return both the
93
+ # name and other information
94
+ # @option options [ true, false ] :authorized_collections A flag, when
95
+ # set to true and used with nameOnly: true, that allows a user without the
96
+ # required privilege to run the command when access control is enforced
97
+ #
84
98
  # See https://docs.mongodb.com/manual/reference/command/listCollections/
85
99
  # for more information and usage.
86
100
  #
87
101
  # @return [ Array<Hash> ] Info for each collection in the database.
88
102
  #
89
- # @since 2.0.5
90
- def list_collections(**options)
103
+ # @since 2.0.5
104
+ def list_collections(options = {})
91
105
  session = client.send(:get_session)
92
- collections_info(session, ServerSelector.primary, **options)
106
+ collections_info(session, ServerSelector.primary, options)
93
107
  end
94
108
 
95
109
  # Create the new database view.
@@ -166,6 +180,7 @@ module Mongo
166
180
  }.tap do |spec|
167
181
  spec[:selector][:nameOnly] = true if options[:name_only]
168
182
  spec[:selector][:filter] = options[:filter] if options[:filter]
183
+ spec[:selector][:authorizedCollections] = true if options[:authorized_collections]
169
184
  end
170
185
  end
171
186
 
@@ -0,0 +1,55 @@
1
+ # Copyright (C) 2020 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ # This is a semaphore that distinguishes waits ending due to the timeout
17
+ # being reached from waits ending due to the semaphore being signaled.
18
+ #
19
+ # @api private
20
+ class DistinguishingSemaphore
21
+ def initialize
22
+ @lock = Mutex.new
23
+ @cv = ConditionVariable.new
24
+ @queue = []
25
+ end
26
+
27
+ # Waits for the semaphore to be signaled up to timeout seconds.
28
+ # If semaphore is not signaled, returns after timeout seconds.
29
+ #
30
+ # @return [ true | false ] true if semaphore was signaled, false if
31
+ # timeout was reached.
32
+ def wait(timeout = nil)
33
+ @lock.synchronize do
34
+ @cv.wait(@lock, timeout)
35
+ (!@queue.empty?).tap do
36
+ @queue.clear
37
+ end
38
+ end
39
+ end
40
+
41
+ def broadcast
42
+ @lock.synchronize do
43
+ @queue.push(true)
44
+ @cv.broadcast
45
+ end
46
+ end
47
+
48
+ def signal
49
+ @lock.synchronize do
50
+ @queue.push(true)
51
+ @cv.signal
52
+ end
53
+ end
54
+ end
55
+ end