mongo 2.10.5 → 2.11.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/lib/mongo.rb +2 -0
  6. data/lib/mongo/address.rb +4 -0
  7. data/lib/mongo/address/validator.rb +99 -0
  8. data/lib/mongo/auth.rb +7 -2
  9. data/lib/mongo/auth/user.rb +1 -7
  10. data/lib/mongo/background_thread.rb +135 -0
  11. data/lib/mongo/bulk_write/transformable.rb +3 -3
  12. data/lib/mongo/client.rb +74 -16
  13. data/lib/mongo/cluster.rb +193 -41
  14. data/lib/mongo/cluster/periodic_executor.rb +31 -43
  15. data/lib/mongo/cluster/sdam_flow.rb +26 -3
  16. data/lib/mongo/cluster/srv_monitor.rb +127 -0
  17. data/lib/mongo/collection/view/readable.rb +3 -5
  18. data/lib/mongo/collection/view/writable.rb +3 -3
  19. data/lib/mongo/cursor/builder/get_more_command.rb +1 -4
  20. data/lib/mongo/cursor/builder/kill_cursors_command.rb +5 -23
  21. data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
  22. data/lib/mongo/cursor/builder/op_kill_cursors.rb +5 -24
  23. data/lib/mongo/error.rb +1 -0
  24. data/lib/mongo/error/auth_error.rb +1 -1
  25. data/lib/mongo/error/connection_check_out_timeout.rb +7 -8
  26. data/lib/mongo/error/invalid_address.rb +24 -0
  27. data/lib/mongo/error/notable.rb +2 -2
  28. data/lib/mongo/error/operation_failure.rb +3 -3
  29. data/lib/mongo/error/pool_closed_error.rb +11 -4
  30. data/lib/mongo/event.rb +1 -1
  31. data/lib/mongo/grid/file.rb +0 -5
  32. data/lib/mongo/grid/file/chunk.rb +0 -2
  33. data/lib/mongo/grid/fs_bucket.rb +13 -15
  34. data/lib/mongo/grid/stream/write.rb +3 -9
  35. data/lib/mongo/loggable.rb +5 -1
  36. data/lib/mongo/monitoring.rb +1 -0
  37. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +7 -0
  38. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +11 -3
  39. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +11 -3
  40. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +11 -3
  41. data/lib/mongo/monitoring/event/cmap/pool_created.rb +12 -3
  42. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +62 -0
  43. data/lib/mongo/operation/shared/executable.rb +5 -10
  44. data/lib/mongo/operation/shared/sessions_supported.rb +1 -5
  45. data/lib/mongo/protocol/get_more.rb +1 -2
  46. data/lib/mongo/protocol/kill_cursors.rb +13 -6
  47. data/lib/mongo/protocol/serializers.rb +4 -20
  48. data/lib/mongo/retryable.rb +9 -34
  49. data/lib/mongo/semaphore.rb +1 -1
  50. data/lib/mongo/server.rb +113 -42
  51. data/lib/mongo/server/connection.rb +12 -5
  52. data/lib/mongo/server/connection_pool.rb +250 -40
  53. data/lib/mongo/server/connection_pool/populator.rb +58 -0
  54. data/lib/mongo/server/description.rb +9 -2
  55. data/lib/mongo/server/monitor.rb +68 -93
  56. data/lib/mongo/server/monitor/connection.rb +2 -0
  57. data/lib/mongo/server_selector/selectable.rb +13 -5
  58. data/lib/mongo/session.rb +0 -13
  59. data/lib/mongo/srv.rb +17 -0
  60. data/lib/mongo/srv/monitor.rb +96 -0
  61. data/lib/mongo/srv/resolver.rb +130 -0
  62. data/lib/mongo/srv/result.rb +126 -0
  63. data/lib/mongo/srv/warning_result.rb +35 -0
  64. data/lib/mongo/uri.rb +45 -55
  65. data/lib/mongo/uri/srv_protocol.rb +89 -42
  66. data/lib/mongo/version.rb +1 -1
  67. data/mongo.gemspec +3 -4
  68. data/spec/README.md +6 -1
  69. data/spec/enterprise_auth/kerberos_spec.rb +7 -6
  70. data/spec/integration/change_stream_examples_spec.rb +0 -4
  71. data/spec/integration/client_construction_spec.rb +14 -2
  72. data/spec/integration/connect_single_rs_name_spec.rb +2 -2
  73. data/spec/integration/connection_pool_populator_spec.rb +296 -0
  74. data/spec/integration/connection_spec.rb +31 -22
  75. data/spec/integration/cursor_reaping_spec.rb +1 -2
  76. data/spec/integration/docs_examples_spec.rb +0 -4
  77. data/spec/integration/heartbeat_events_spec.rb +17 -15
  78. data/spec/integration/reconnect_spec.rb +144 -1
  79. data/spec/integration/retryable_writes_errors_spec.rb +0 -4
  80. data/spec/integration/retryable_writes_spec.rb +36 -36
  81. data/spec/integration/sdam_error_handling_spec.rb +31 -25
  82. data/spec/integration/sdam_events_spec.rb +2 -6
  83. data/spec/integration/server_monitor_spec.rb +28 -0
  84. data/spec/integration/server_selector_spec.rb +7 -5
  85. data/spec/integration/srv_monitoring_spec.rb +360 -0
  86. data/spec/integration/step_down_spec.rb +4 -6
  87. data/spec/lite_spec_helper.rb +22 -0
  88. data/spec/mongo/address/validator_spec.rb +51 -0
  89. data/spec/mongo/auth/cr_spec.rb +1 -29
  90. data/spec/mongo/auth/ldap_spec.rb +1 -29
  91. data/spec/mongo/auth/scram/conversation_spec.rb +0 -2
  92. data/spec/mongo/auth/scram/negotiation_spec.rb +1 -1
  93. data/spec/mongo/auth/scram_spec.rb +1 -29
  94. data/spec/mongo/auth/user/view_spec.rb +1 -36
  95. data/spec/mongo/auth/user_spec.rb +0 -12
  96. data/spec/mongo/auth/x509_spec.rb +1 -29
  97. data/spec/mongo/bulk_write_spec.rb +2 -2
  98. data/spec/mongo/client_construction_spec.rb +56 -15
  99. data/spec/mongo/client_spec.rb +31 -27
  100. data/spec/mongo/cluster/periodic_executor_spec.rb +16 -0
  101. data/spec/mongo/cluster/srv_monitor_spec.rb +214 -0
  102. data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -11
  103. data/spec/mongo/cluster/topology/sharded_spec.rb +12 -9
  104. data/spec/mongo/cluster/topology/single_spec.rb +20 -11
  105. data/spec/mongo/cluster_spec.rb +45 -29
  106. data/spec/mongo/collection/view/map_reduce_spec.rb +14 -9
  107. data/spec/mongo/collection/view/readable_spec.rb +0 -16
  108. data/spec/mongo/collection_spec.rb +0 -44
  109. data/spec/mongo/cursor/builder/get_more_command_spec.rb +2 -4
  110. data/spec/mongo/cursor/builder/op_get_more_spec.rb +2 -4
  111. data/spec/mongo/cursor_spec.rb +27 -7
  112. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +10 -3
  113. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +10 -3
  114. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +10 -3
  115. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +10 -3
  116. data/spec/mongo/operation/delete/op_msg_spec.rb +17 -8
  117. data/spec/mongo/operation/insert/op_msg_spec.rb +50 -35
  118. data/spec/mongo/operation/update/op_msg_spec.rb +14 -7
  119. data/spec/mongo/retryable_spec.rb +52 -31
  120. data/spec/mongo/server/app_metadata_spec.rb +0 -8
  121. data/spec/mongo/server/connection_auth_spec.rb +5 -2
  122. data/spec/mongo/server/connection_pool/populator_spec.rb +101 -0
  123. data/spec/mongo/server/connection_pool_spec.rb +256 -107
  124. data/spec/mongo/server/connection_spec.rb +22 -33
  125. data/spec/mongo/server/description_spec.rb +42 -4
  126. data/spec/mongo/server/monitor/connection_spec.rb +22 -11
  127. data/spec/mongo/server/monitor_spec.rb +66 -107
  128. data/spec/mongo/server_spec.rb +82 -60
  129. data/spec/mongo/session/session_pool_spec.rb +1 -5
  130. data/spec/mongo/session_spec.rb +0 -4
  131. data/spec/mongo/socket/ssl_spec.rb +2 -2
  132. data/spec/mongo/srv/monitor_spec.rb +211 -0
  133. data/spec/mongo/srv/result_spec.rb +54 -0
  134. data/spec/mongo/uri/srv_protocol_spec.rb +30 -15
  135. data/spec/mongo/uri_spec.rb +125 -4
  136. data/spec/spec_helper.rb +6 -0
  137. data/spec/spec_tests/auth_spec.rb +39 -0
  138. data/spec/spec_tests/cmap_spec.rb +55 -8
  139. data/spec/spec_tests/connection_string_spec.rb +6 -31
  140. data/spec/spec_tests/data/auth/connection-string.yml +297 -0
  141. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +4 -1
  142. data/spec/spec_tests/data/cmap/pool-create-with-options.yml +1 -0
  143. data/spec/spec_tests/data/command_monitoring/insertMany.yml +1 -1
  144. data/spec/spec_tests/data/connection_string/invalid-uris.yml +20 -0
  145. data/spec/spec_tests/data/connection_string/valid-auth.yml +16 -0
  146. data/spec/spec_tests/data/connection_string/valid-warnings.yml +26 -30
  147. data/spec/spec_tests/data/transactions/abort.yml +3 -3
  148. data/spec/spec_tests/data/transactions/error-labels.yml +3 -3
  149. data/spec/spec_tests/data/transactions_api/callback-retry.yml +3 -3
  150. data/spec/spec_tests/data/uri_options/auth-options.yml +1 -1
  151. data/spec/spec_tests/max_staleness_spec.rb +7 -2
  152. data/spec/spec_tests/retryable_reads_spec.rb +0 -31
  153. data/spec/spec_tests/sdam_monitoring_spec.rb +12 -12
  154. data/spec/spec_tests/sdam_spec.rb +4 -7
  155. data/spec/spec_tests/server_selection_spec.rb +6 -2
  156. data/spec/spec_tests/transactions_spec.rb +0 -2
  157. data/spec/spec_tests/uri_options_spec.rb +4 -2
  158. data/spec/stress/connection_pool_stress_spec.rb +203 -0
  159. data/spec/stress/connection_pool_timing_spec.rb +181 -0
  160. data/spec/support/auth.rb +113 -0
  161. data/spec/support/background_thread_registry.rb +63 -0
  162. data/spec/support/client_registry.rb +11 -2
  163. data/spec/support/cluster_config.rb +65 -46
  164. data/spec/support/cluster_tools.rb +2 -2
  165. data/spec/support/cmap.rb +13 -14
  166. data/spec/support/cmap/verifier.rb +4 -5
  167. data/spec/support/command_monitoring.rb +0 -5
  168. data/spec/support/common_shortcuts.rb +101 -1
  169. data/spec/support/constraints.rb +25 -0
  170. data/spec/support/dns.rb +13 -0
  171. data/spec/support/event_subscriber.rb +0 -7
  172. data/spec/support/json_ext_formatter.rb +5 -1
  173. data/spec/support/lite_constraints.rb +22 -6
  174. data/spec/support/local_resource_registry.rb +34 -0
  175. data/spec/support/sdam_monitoring.rb +115 -0
  176. data/spec/support/spec_config.rb +20 -6
  177. data/spec/support/spec_setup.rb +2 -2
  178. data/spec/support/transactions.rb +1 -1
  179. data/spec/support/transactions/test.rb +1 -1
  180. data/spec/support/utils.rb +1 -16
  181. metadata +685 -659
  182. metadata.gz.sig +0 -0
  183. data/lib/mongo/event/description_changed.rb +0 -52
  184. data/spec/integration/bson_symbol_spec.rb +0 -34
  185. data/spec/integration/crud_spec.rb +0 -45
  186. data/spec/integration/get_more_spec.rb +0 -32
  187. data/spec/integration/grid_fs_bucket_spec.rb +0 -48
  188. data/spec/integration/retryable_errors_spec.rb +0 -265
  189. data/spec/integration/size_limit_spec.rb~12e1e9c4f... RUBY-2242 Fix zlib compression (#2021) +0 -98
  190. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +0 -56
  191. data/spec/runners/sdam/verifier.rb +0 -88
@@ -66,20 +66,15 @@ module Mongo
66
66
 
67
67
  if result.not_master? || result.node_recovering?
68
68
  if result.node_shutting_down?
69
- disconnect_pool = true
69
+ keep_pool = false
70
70
  else
71
- # Max wire version needs to be checked prior to marking the
72
- # server unknown
73
- disconnect_pool = !server.description.server_version_gte?('4.2')
71
+ # Max wire version needs to be examined while the server is known
72
+ keep_pool = server.description.server_version_gte?('4.2')
74
73
  end
75
74
 
76
- server.unknown!
75
+ server.unknown!(keep_connection_pool: keep_pool)
77
76
 
78
- if disconnect_pool
79
- server.pool.disconnect!
80
- end
81
-
82
- server.monitor.scan_semaphore.signal
77
+ server.scan_semaphore.signal
83
78
  end
84
79
 
85
80
  session.process(result) if session
@@ -95,10 +95,6 @@ module Mongo
95
95
  session.add_autocommit!(selector)
96
96
  end
97
97
 
98
- def apply_session_id!(selector)
99
- session.add_id!(selector)
100
- end
101
-
102
98
  def apply_start_transaction!(selector)
103
99
  session.add_start_transaction!(selector)
104
100
  end
@@ -146,7 +142,7 @@ module Mongo
146
142
  def apply_session_options(sel, server)
147
143
  apply_cluster_time!(sel, server)
148
144
  sel[:txnNumber] = BSON::Int64.new(txn_num) if txn_num
149
- apply_session_id!(sel)
145
+ sel.merge!(lsid: session.session_id)
150
146
  apply_start_transaction!(sel)
151
147
  apply_causal_consistency!(sel, server)
152
148
  apply_autocommit!(sel)
@@ -110,7 +110,6 @@ module Mongo
110
110
  # The get more constant.
111
111
  #
112
112
  # @since 2.2.0
113
- # @deprecated
114
113
  GET_MORE = 'getMore'.freeze
115
114
 
116
115
  # @return [ String ] collection The name of the collection.
@@ -149,7 +148,7 @@ module Mongo
149
148
  # @since 2.1.0
150
149
  def command
151
150
  document = BSON::Document.new
152
- document.store('getMore', BSON::Int64.new(cursor_id))
151
+ document.store(GET_MORE, cursor_id)
153
152
  document.store(Message::BATCH_SIZE, number_to_return)
154
153
  document.store(Message::COLLECTION, collection)
155
154
  document
@@ -52,7 +52,7 @@ module Mongo
52
52
  command_name: 'killCursors',
53
53
  database_name: @database,
54
54
  command: upconverter.command,
55
- request_id: request_id,
55
+ request_id: request_id
56
56
  )
57
57
  end
58
58
 
@@ -85,6 +85,16 @@ module Mongo
85
85
  # @since 2.1.0
86
86
  class Upconverter
87
87
 
88
+ # The kill cursors constant.
89
+ #
90
+ # @since 2.2.0
91
+ KILL_CURSORS = 'killCursors'.freeze
92
+
93
+ # The cursors constant.
94
+ #
95
+ # @since 2.2.0
96
+ CURSORS = 'cursors'.freeze
97
+
88
98
  # @return [ String ] collection The name of the collection.
89
99
  attr_reader :collection
90
100
 
@@ -115,11 +125,8 @@ module Mongo
115
125
  # @since 2.1.0
116
126
  def command
117
127
  document = BSON::Document.new
118
- document.store('killCursors', collection)
119
- store_ids = cursor_ids.map do |cursor_id|
120
- BSON::Int64.new(cursor_id)
121
- end
122
- document.store('cursors', store_ids)
128
+ document.store(KILL_CURSORS, collection)
129
+ document.store(CURSORS, cursor_ids)
123
130
  document
124
131
  end
125
132
  end
@@ -102,21 +102,13 @@ module Mongo
102
102
  # Serializes and de-serializes one 32-bit integer.
103
103
  module Int32
104
104
 
105
- # Serializes a number to a 32-bit integer
105
+ # Serializes a fixnum to a 4-byte 32-bit integer
106
106
  #
107
107
  # @param buffer [ String ] Buffer to receive the serialized Int32.
108
- # @param value [ Integer | BSON::Int32 ] 32-bit integer to be serialized.
108
+ # @param value [ Fixnum ] 32-bit integer to be serialized.
109
109
  #
110
110
  # @return [String] Buffer with serialized value.
111
111
  def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
112
- if value.is_a?(BSON::Int32)
113
- if value.respond_to?(:value)
114
- # bson-ruby >= 4.6.0
115
- value = value.value
116
- else
117
- value = value.instance_variable_get('@integer')
118
- end
119
- end
120
112
  buffer.put_int32(value)
121
113
  end
122
114
 
@@ -135,21 +127,13 @@ module Mongo
135
127
  # Serializes and de-serializes one 64-bit integer.
136
128
  module Int64
137
129
 
138
- # Serializes a number to a 64-bit integer
130
+ # Serializes a fixnum to an 8-byte 64-bit integer
139
131
  #
140
132
  # @param buffer [ String ] Buffer to receive the serialized Int64.
141
- # @param value [ Integer | BSON::Int64 ] 64-bit integer to be serialized.
133
+ # @param value [ Fixnum ] 64-bit integer to be serialized.
142
134
  #
143
135
  # @return [ String ] Buffer with serialized value.
144
136
  def self.serialize(buffer, value, validating_keys = BSON::Config.validating_keys?)
145
- if value.is_a?(BSON::Int64)
146
- if value.respond_to?(:value)
147
- # bson-ruby >= 4.6.0
148
- value = value.value
149
- else
150
- value = value.instance_variable_get('@integer')
151
- end
152
- end
153
137
  buffer.put_int64(value)
154
138
  end
155
139
 
@@ -119,12 +119,7 @@ module Mongo
119
119
  legacy_read_with_retry(session, server_selector, &block)
120
120
  else
121
121
  server = select_server(cluster, server_selector, session)
122
- begin
123
- yield server
124
- rescue Error::SocketError, Error::SocketTimeoutError, Error::OperationFailure => e
125
- e.add_note('retries disabled')
126
- raise e
127
- end
122
+ yield server
128
123
  end
129
124
  end
130
125
 
@@ -219,14 +214,12 @@ module Mongo
219
214
  begin
220
215
  yield(server, txn_num, false)
221
216
  rescue Error::SocketError, Error::SocketTimeoutError => e
222
- e.add_note('modern retry')
223
217
  e.add_note("attempt 1")
224
218
  if session.in_transaction? && !ending_transaction
225
219
  raise e
226
220
  end
227
221
  retry_write(e, session, txn_num, &block)
228
222
  rescue Error::OperationFailure => e
229
- e.add_note('modern retry')
230
223
  e.add_note("attempt 1")
231
224
  if e.unsupported_retryable_write?
232
225
  raise_unsupported_error(e)
@@ -257,12 +250,7 @@ module Mongo
257
250
  def nro_write_with_retry(session, write_concern, &block)
258
251
  if session && session.client.options[:retry_writes]
259
252
  server = select_server(cluster, ServerSelector.primary, session)
260
- begin
261
- yield server
262
- rescue Error::SocketError, Error::SocketTimeoutError, Error::OperationFailure => e
263
- e.add_note('retries disabled')
264
- raise e
265
- end
253
+ yield server
266
254
  else
267
255
  legacy_write_with_retry(nil, session, &block)
268
256
  end
@@ -292,8 +280,7 @@ module Mongo
292
280
  server ||= select_server(cluster, ServerSelector.primary, session)
293
281
  yield server
294
282
  rescue Error::OperationFailure => e
295
- e.add_note('legacy retry')
296
- e.add_note("attempt #{attempt}")
283
+ e.add_note("attempt #{attempt + 1}")
297
284
  server = nil
298
285
  if attempt > client.max_write_retries
299
286
  raise e
@@ -311,19 +298,18 @@ module Mongo
311
298
  private
312
299
 
313
300
  def modern_read_with_retry(session, server_selector, &block)
301
+ attempt = 0
314
302
  server = select_server(cluster, server_selector, session)
315
303
  begin
316
304
  yield server
317
305
  rescue Error::SocketError, Error::SocketTimeoutError => e
318
- e.add_note('modern retry')
319
- e.add_note("attempt 1")
306
+ e.add_note("attempt #{attempt + 1}")
320
307
  if session.in_transaction?
321
308
  raise e
322
309
  end
323
310
  retry_read(e, server_selector, session, &block)
324
311
  rescue Error::OperationFailure => e
325
- e.add_note('modern retry')
326
- e.add_note("attempt 1")
312
+ e.add_note("attempt #{attempt + 1}")
327
313
  if session.in_transaction? || !e.write_retryable?
328
314
  raise e
329
315
  end
@@ -338,8 +324,7 @@ module Mongo
338
324
  attempt += 1
339
325
  yield server
340
326
  rescue Error::SocketError, Error::SocketTimeoutError => e
341
- e.add_note('legacy retry')
342
- e.add_note("attempt #{attempt}")
327
+ e.add_note("attempt #{attempt + 1}")
343
328
  if attempt > client.max_read_retries || (session && session.in_transaction?)
344
329
  raise e
345
330
  end
@@ -347,9 +332,8 @@ module Mongo
347
332
  server = select_server(cluster, server_selector, session)
348
333
  retry
349
334
  rescue Error::OperationFailure => e
350
- e.add_note('legacy retry')
351
- e.add_note("attempt #{attempt}")
352
- if e.retryable? && !(session && session.in_transaction?)
335
+ e.add_note("attempt #{attempt + 1}")
336
+ if cluster.sharded? && e.retryable? && !(session && session.in_transaction?)
353
337
  if attempt > client.max_read_retries
354
338
  raise e
355
339
  end
@@ -391,11 +375,9 @@ module Mongo
391
375
  begin
392
376
  yield server, true
393
377
  rescue Error::SocketError, Error::SocketTimeoutError => e
394
- e.add_note('modern retry')
395
378
  e.add_note("attempt 2")
396
379
  raise e
397
380
  rescue Error::OperationFailure => e
398
- e.add_note('modern retry')
399
381
  unless e.write_retryable?
400
382
  original_error.add_note("later retry failed: #{e.class}: #{e}")
401
383
  raise original_error
@@ -403,7 +385,6 @@ module Mongo
403
385
  e.add_note("attempt 2")
404
386
  raise e
405
387
  rescue => e
406
- e.add_note('modern retry')
407
388
  original_error.add_note("later retry failed: #{e.class}: #{e}")
408
389
  raise original_error
409
390
  end
@@ -417,19 +398,15 @@ module Mongo
417
398
  # server unknown). Here we just need to wait for server selection.
418
399
  server = select_server(cluster, ServerSelector.primary, session)
419
400
  unless server.retry_writes?
420
- # Do not need to add "modern retry" here, it should already be on
421
- # the first exception.
422
401
  original_error.add_note('did not retry because server selected for retry does not supoprt retryable writes')
423
402
  raise original_error
424
403
  end
425
404
  log_retry(original_error, message: 'Write retry')
426
405
  yield(server, txn_num, true)
427
406
  rescue Error::SocketError, Error::SocketTimeoutError => e
428
- e.add_note('modern retry')
429
407
  e.add_note('attempt 2')
430
408
  raise e
431
409
  rescue Error::OperationFailure => e
432
- e.add_note('modern retry')
433
410
  if e.write_retryable?
434
411
  e.add_note('attempt 2')
435
412
  raise e
@@ -438,8 +415,6 @@ module Mongo
438
415
  raise original_error
439
416
  end
440
417
  rescue => e
441
- # Do not need to add "modern retry" here, it should already be on
442
- # the first exception.
443
418
  original_error.add_note("later retry failed: #{e.class}: #{e}")
444
419
  raise original_error
445
420
  end
@@ -25,7 +25,7 @@ module Mongo
25
25
 
26
26
  # Waits for the semaphore to be signaled up to timeout seconds.
27
27
  # If semaphore is not signaled, returns after timeout seconds.
28
- def wait(timeout)
28
+ def wait(timeout = nil)
29
29
  @lock.synchronize do
30
30
  @cv.wait(@lock, timeout)
31
31
  end
data/lib/mongo/server.rb CHANGED
@@ -58,16 +58,24 @@ module Mongo
58
58
  @cluster = cluster
59
59
  @monitoring = monitoring
60
60
  options = options.dup
61
- monitor = options.delete(:monitor)
61
+ _monitor = options.delete(:monitor)
62
62
  @options = options.freeze
63
63
  @event_listeners = event_listeners
64
64
  @connection_id_gen = Class.new do
65
65
  include Id
66
66
  end
67
- @monitor = Monitor.new(address, event_listeners, monitoring,
68
- options.merge(app_metadata: Monitor::AppMetadata.new(cluster.options)))
69
- unless monitor == false
70
- start_monitoring
67
+ @scan_semaphore = Semaphore.new
68
+ @round_trip_time_averager = RoundTripTimeAverager.new
69
+ @description = Description.new(address, {})
70
+ @last_scan = nil
71
+ unless options[:monitoring_io] == false
72
+ @monitor = Monitor.new(self, event_listeners, monitoring,
73
+ options.merge(
74
+ app_metadata: Monitor::AppMetadata.new(cluster.options),
75
+ ))
76
+ unless _monitor == false
77
+ start_monitoring
78
+ end
71
79
  end
72
80
  @connected = true
73
81
  @pool_lock = Mutex.new
@@ -79,7 +87,8 @@ module Mongo
79
87
  # @return [ Cluster ] cluster The server cluster.
80
88
  attr_reader :cluster
81
89
 
82
- # @return [ Monitor ] monitor The server monitor.
90
+ # @return [ nil | Monitor ] monitor The server monitor. nil if the servenr
91
+ # was created with monitoring_io: false option.
83
92
  attr_reader :monitor
84
93
 
85
94
  # @return [ Hash ] The options hash.
@@ -88,15 +97,46 @@ module Mongo
88
97
  # @return [ Monitoring ] monitoring The monitoring.
89
98
  attr_reader :monitoring
90
99
 
91
- # Get the description from the monitor and scan on monitor.
92
- def_delegators :monitor,
93
- :description,
94
- :scan!,
95
- :heartbeat_frequency,
96
- :last_scan,
97
- :compressor
100
+ # @return [ Server::Description ] description The server
101
+ # description the monitor refreshes.
102
+ attr_reader :description
103
+
104
+ # @return [ Time | nil ] last_scan The time when the last server scan
105
+ # completed, or nil if the server has not been scanned yet.
106
+ #
107
+ # @since 2.4.0
108
+ def last_scan
109
+ if description && !description.config.empty?
110
+ description.last_update_time
111
+ else
112
+ @last_scan
113
+ end
114
+ end
115
+
116
+ # @deprecated
117
+ def heartbeat_frequency
118
+ cluster.heartbeat_interval
119
+ end
120
+
121
+ # @deprecated
98
122
  alias :heartbeat_frequency_seconds :heartbeat_frequency
99
123
 
124
+ # @deprecated
125
+ def_delegators :monitor, :scan!
126
+
127
+ # The last compressor discovered by the server monitor.
128
+ #
129
+ # The compressor state should be determined for each individual
130
+ # connection rather than kept per server. A future version of the
131
+ # driver will change how compressors are tracked and used.
132
+ def compressor
133
+ if monitor
134
+ monitor.compressor
135
+ else
136
+ nil
137
+ end
138
+ end
139
+
100
140
  # Delegate convenience methods to the monitor description.
101
141
  def_delegators :description,
102
142
  :arbiter?,
@@ -127,6 +167,16 @@ module Mongo
127
167
  def_delegators :features,
128
168
  :check_driver_support!
129
169
 
170
+ # @return [ Semaphore ] Semaphore to signal to request an immediate scan
171
+ # of this server by its monitor, if one is running.
172
+ #
173
+ # @api private
174
+ attr_reader :scan_semaphore
175
+
176
+ # @return [ RoundTripTimeAverager ] Round trip time averager object.
177
+ # @api private
178
+ attr_reader :round_trip_time_averager
179
+
130
180
  # Is this server equal to another?
131
181
  #
132
182
  # @example Is the server equal to the other?
@@ -169,26 +219,37 @@ module Mongo
169
219
  # @deprecated No longer necessary with Server Selection specification.
170
220
  def connectable?; end
171
221
 
172
- # Disconnect the server from the connection.
173
- #
174
- # @example Disconnect the server.
175
- # server.disconnect!
222
+ # Disconnect the driver from this server.
176
223
  #
177
- # @param [ Boolean ] wait Whether to wait for background threads to
178
- # finish running.
224
+ # Disconnects all idle connections to this server in its connection pool,
225
+ # if any exist. Stops the populator of the connection pool, if it is
226
+ # running. Does not immediately close connections which are presently
227
+ # checked out (i.e. in use) - such connections will be closed when they
228
+ # are returned to their respective connection pools. Stop the server's
229
+ # background monitor.
179
230
  #
180
- # @return [ true ] Always true with no exception.
231
+ # @return [ true ] Always true.
181
232
  #
182
233
  # @since 2.0.0
183
- def disconnect!(wait=false)
184
- begin
234
+ def disconnect!
235
+ if monitor
236
+ monitor.stop!
237
+ end
238
+ _pool = @pool_lock.synchronize do
239
+ @pool
240
+ end
241
+ if _pool
185
242
  # For backwards compatibility we disconnect/clear the pool rather
186
- # than close it here.
187
- pool.disconnect!
188
- rescue Error::PoolClosedError
189
- # If the pool was already closed, we don't need to do anything here.
243
+ # than close it here. We also stop the populator which allows the
244
+ # the pool to continue providing connections but stops it from
245
+ # connecting in background on clients/servers that are in fact
246
+ # intended to be closed and no longer used.
247
+ begin
248
+ _pool.disconnect!(stop_populator: true)
249
+ rescue Error::PoolClosedError
250
+ # If the pool was already closed, we don't need to do anything here.
251
+ end
190
252
  end
191
- monitor.stop!(wait)
192
253
  @connected = false
193
254
  true
194
255
  end
@@ -228,8 +289,8 @@ module Mongo
228
289
  Monitoring::Event::ServerOpening.new(address, cluster.topology)
229
290
  )
230
291
  if options[:monitoring_io] != false
231
- monitor.run!
232
292
  ObjectSpace.define_finalizer(self, self.class.finalize(monitor))
293
+ monitor.run!
233
294
  end
234
295
  end
235
296
 
@@ -275,11 +336,17 @@ module Mongo
275
336
  if replica_set_name
276
337
  status += " replica_set=#{replica_set_name}"
277
338
  end
339
+
340
+ if @pool
341
+ status += " pool=#{@pool.summary}"
342
+ end
343
+
278
344
  address_bit = if address
279
345
  "#{address.host}:#{address.port}"
280
346
  else
281
347
  'nil'
282
348
  end
349
+
283
350
  "#<Server address=#{address_bit} #{status}>"
284
351
  end
285
352
 
@@ -374,7 +441,6 @@ module Mongo
374
441
  rescue Mongo::Error::SocketError
375
442
  # non-timeout network error
376
443
  unknown!
377
- pool.disconnect!
378
444
  raise
379
445
  rescue Auth::Unauthorized
380
446
  # auth error, keep server description and topology as they are
@@ -407,24 +473,24 @@ module Mongo
407
473
  # Marks server unknown and publishes the associated SDAM event
408
474
  # (server description changed).
409
475
  #
476
+ # @param [ Hash ] options Options.
477
+ #
478
+ # @option options [ true | false ] :keep_connection_pool Usually when the
479
+ # new server description is unknown, the connection pool on the
480
+ # respective server is cleared. Set this option to true to keep the
481
+ # existing connection pool (required when handling not master errors
482
+ # on 4.2+ servers).
483
+ #
410
484
  # @since 2.4.0, SDAM events are sent as of version 2.7.0
411
- def unknown!
412
- # Just dispatch the description changed event here, SDAM flow
413
- # will update description on the server without in-place mutations
414
- # and invoke SDAM transitions as needed.
415
- publish(Event::DESCRIPTION_CHANGED, description, Description.new(address))
485
+ def unknown!(options = {})
486
+ # SDAM flow will update description on the server without in-place
487
+ # mutations and invoke SDAM transitions as needed.
488
+ cluster.run_sdam_flow(description, Description.new(address), options)
416
489
  end
417
490
 
418
491
  # @api private
419
492
  def update_description(description)
420
- prev_description = monitor.instance_variable_get('@description')
421
- monitor.instance_variable_set('@description', description)
422
- if description.unknown? && !prev_description.unknown?
423
- # This clears redundantly sometimes and also clears the pool on
424
- # 4.2+ servers after not master errors which should not be done.
425
- # Driver version 2.11+ has the correct implementation.
426
- clear_connection_pool
427
- end
493
+ @description = description
428
494
  end
429
495
 
430
496
  # @api private
@@ -440,6 +506,11 @@ module Mongo
440
506
  def next_connection_id
441
507
  @connection_id_gen.next_id
442
508
  end
509
+
510
+ # @api private
511
+ def update_last_scan
512
+ @last_scan = Time.now
513
+ end
443
514
  end
444
515
  end
445
516