mongo 2.10.5 → 2.11.0.rc0

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 (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
@@ -0,0 +1,58 @@
1
+ # Copyright (C) 2019 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
+ class Server
17
+ # A manager that maintains the invariant that the
18
+ # size of a connection pool is at least minPoolSize.
19
+ #
20
+ # @api private
21
+ class Populator
22
+ include BackgroundThread
23
+
24
+ # @param [ Server::ConnectionPool ] The connection pool.
25
+ # @param [ Hash ] options The options.
26
+ #
27
+ # @option options [ Logger ] :logger A custom logger to use.
28
+ def initialize(pool, options = {})
29
+ @pool = pool
30
+ @thread = nil
31
+ @options = options
32
+ end
33
+
34
+ attr_reader :options
35
+
36
+ def pre_stop
37
+ @pool.populate_semaphore.signal
38
+ end
39
+
40
+ private
41
+
42
+ def do_work
43
+ throw(:done) if @pool.closed?
44
+
45
+ begin
46
+ unless @pool.populate
47
+ @pool.populate_semaphore.wait
48
+ end
49
+ rescue Error::AuthError, Error => e
50
+ # Errors encountered when trying to add connections to
51
+ # pool; try again later
52
+ log_warn("Populator failed to connect a connection for #{@pool.address}: #{e.class}: #{e}.")
53
+ @pool.populate_semaphore.wait(5)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -619,6 +619,7 @@ module Mongo
619
619
  # @return [ true, false ] If the description is from the server.
620
620
  #
621
621
  # @since 2.0.6
622
+ # @deprecated
622
623
  def is_server?(server)
623
624
  address == server.address
624
625
  end
@@ -632,6 +633,7 @@ module Mongo
632
633
  # of servers.
633
634
  #
634
635
  # @since 2.0.6
636
+ # @deprecated
635
637
  def lists_server?(server)
636
638
  servers.include?(server.address.to_s)
637
639
  end
@@ -683,9 +685,14 @@ module Mongo
683
685
  end
684
686
  end
685
687
 
686
- # Time when the server was last checked.
688
+ # Time when this server description was created.
687
689
  #
688
- # @return [ Time ] Last check time.
690
+ # @note This time does not indicate when a successful server check
691
+ # completed, because marking a server unknown updates its description
692
+ # and last_update_time. Use Server#last_scan to find out when the server
693
+ # was last successfully checked by its Monitor.
694
+ #
695
+ # @return [ Time ] Server description creation time.
689
696
  #
690
697
  # @since 2.7.0
691
698
  attr_reader :last_update_time
@@ -15,14 +15,18 @@
15
15
  module Mongo
16
16
  class Server
17
17
 
18
- # This object is responsible for keeping server status up to date, running in
19
- # a separate thread as to not disrupt other operations.
18
+ # Responsible for periodically polling a server via ismaster commands to
19
+ # keep the server's status up to date.
20
+ #
21
+ # Does all work in a background thread so as to not interfere with other
22
+ # operations performed by the driver.
20
23
  #
21
24
  # @since 2.0.0
22
25
  class Monitor
23
26
  include Loggable
24
27
  extend Forwardable
25
28
  include Event::Publisher
29
+ include BackgroundThread
26
30
 
27
31
  # The default time for a server to refresh its status is 10 seconds.
28
32
  #
@@ -48,45 +52,45 @@ module Mongo
48
52
  #
49
53
  # @note Monitor must never be directly instantiated outside of a Server.
50
54
  #
51
- # @param [ Address ] address The address to monitor.
55
+ # @param [ Server ] server The server to monitor.
52
56
  # @param [ Event::Listeners ] event_listeners The event listeners.
53
57
  # @param [ Monitoring ] monitoring The monitoring..
54
58
  # @param [ Hash ] options The options.
55
- # @option options [ Float ] :heartbeat_frequency The interval, in seconds,
56
- # between server description refreshes via ismaster.
59
+ #
60
+ # @option options [ Float ] :connect_timeout The timeout, in seconds, to
61
+ # use when establishing the monitoring connection.
62
+ # @option options [ Logger ] :logger A custom logger to use.
63
+ # @option options [ Float ] :socket_timeout The timeout, in seconds, to
64
+ # execute operations on the monitoring connection.
57
65
  #
58
66
  # @since 2.0.0
59
67
  # @api private
60
- def initialize(address, event_listeners, monitoring, options = {})
68
+ def initialize(server, event_listeners, monitoring, options = {})
61
69
  unless monitoring.is_a?(Monitoring)
62
70
  raise ArgumentError, "Wrong monitoring type: #{monitoring.inspect}"
63
71
  end
64
- @description = Description.new(address, {})
72
+ @server = server
65
73
  @event_listeners = event_listeners
66
74
  @monitoring = monitoring
67
75
  @options = options.freeze
68
- @round_trip_time_averager = RoundTripTimeAverager.new
69
- @scan_semaphore = Semaphore.new
70
76
  # This is a Mongo::Server::Monitor::Connection
71
- @connection = Connection.new(address, options)
72
- @last_scan = nil
77
+ @connection = Connection.new(server.address, options)
73
78
  @mutex = Mutex.new
79
+ @scan_started_at = nil
74
80
  end
75
81
 
82
+ # @return [ Server ] server The server that this monitor is monitoring.
83
+ # @api private
84
+ attr_reader :server
85
+
76
86
  # @return [ Mongo::Server::Monitor::Connection ] connection The connection to use.
77
87
  attr_reader :connection
78
88
 
79
- # @return [ Server::Description ] description The server
80
- # description the monitor refreshes.
81
- attr_reader :description
82
-
83
89
  # @return [ Hash ] options The server options.
84
90
  attr_reader :options
85
91
 
86
- # @return [ Time ] last_scan The time when the last server scan started.
87
- #
88
- # @since 2.4.0
89
- attr_reader :last_scan
92
+ # @deprecated
93
+ def_delegators :server, :last_scan
90
94
 
91
95
  # The compressor is determined during the handshake, so it must be an attribute
92
96
  # of the connection.
@@ -98,19 +102,14 @@ module Mongo
98
102
  # Get the refresh interval for the server. This will be defined via an
99
103
  # option or will default to 10.
100
104
  #
101
- # @example Get the refresh interval.
102
- # server.heartbeat_frequency
103
- #
104
- # @return [ Integer ] The heartbeat frequency, in seconds.
105
+ # @return [ Float ] The heartbeat interval, in seconds.
105
106
  #
106
107
  # @since 2.0.0
108
+ # @deprecated
107
109
  def heartbeat_frequency
108
- @heartbeat_frequency ||= options[:heartbeat_frequency] || HEARTBEAT_FREQUENCY
110
+ server.cluster.heartbeat_interval
109
111
  end
110
112
 
111
- # @api private
112
- attr_reader :scan_semaphore
113
-
114
113
  # Runs the server monitor. Refreshing happens on a separate thread per
115
114
  # server.
116
115
  #
@@ -120,12 +119,23 @@ module Mongo
120
119
  # @return [ Thread ] The thread the monitor runs on.
121
120
  #
122
121
  # @since 2.0.0
123
- def run!
124
- @thread = Thread.new(heartbeat_frequency) do |i|
125
- loop do
126
- scan!
127
- @scan_semaphore.wait(i)
128
- end
122
+ def do_work
123
+ scan!
124
+ server.scan_semaphore.wait(server.cluster.heartbeat_interval)
125
+ end
126
+
127
+ # Stop the background thread and wait for to terminate for a reasonable
128
+ # amount of time.
129
+ #
130
+ # @return [ true | false ] Whether the thread was terminated.
131
+ #
132
+ # @api public for backwards compatibility only
133
+ def stop!
134
+ # Forward super's return value
135
+ super.tap do
136
+ # Important: disconnect should happen after the background thread
137
+ # terminated.
138
+ connection.disconnect!
129
139
  end
130
140
  end
131
141
 
@@ -141,6 +151,9 @@ module Mongo
141
151
  # @note If the system clock is set to a time in the past, this method
142
152
  # can sleep for a very long time.
143
153
  #
154
+ # @note The return value of this method is deprecated. In version 3.0.0
155
+ # this method will not have a return value.
156
+ #
144
157
  # @example Run a scan.
145
158
  # monitor.scan!
146
159
  #
@@ -150,55 +163,10 @@ module Mongo
150
163
  def scan!
151
164
  throttle_scan_frequency!
152
165
  result = ismaster
153
- new_description = Description.new(description.address, result,
154
- @round_trip_time_averager.average_round_trip_time)
155
- publish(Event::DESCRIPTION_CHANGED, description, new_description)
156
- # If this server's response has a mismatched me, or for other reasons,
157
- # this server may be removed from topology. When this happens the
158
- # monitor thread gets killed. As a result, any code after the publish
159
- # call may not run in a particular monitor instance, hence there
160
- # shouldn't be any code here.
161
- @description = new_description
162
- # This call can be after the publish event because if the
163
- # monitoring thread gets killed the server is closed and no client
164
- # should be waiting for it
165
- if options[:server_selection_semaphore]
166
- options[:server_selection_semaphore].broadcast
167
- end
168
- @description
169
- end
170
-
171
- # Stops the server monitor. Kills the thread so it doesn't continue
172
- # taking memory and sending commands to the connection.
173
- #
174
- # @example Stop the monitor.
175
- # monitor.stop!
176
- #
177
- # @param [ Boolean ] wait Whether to wait for background threads to
178
- # finish running.
179
- #
180
- # @return [ Boolean ] Is the thread stopped?
181
- #
182
- # @since 2.0.0
183
- def stop!(wait=false)
184
- # Although disconnect! documentation implies a possibility of
185
- # failure, all of our disconnects always return true
186
- if connection.disconnect!
187
- if @thread
188
- @thread.kill
189
- if wait
190
- @thread.join
191
- @thread = nil
192
- true
193
- else
194
- !@thread.alive?
195
- end
196
- else
197
- true
198
- end
199
- else
200
- false
201
- end
166
+ new_description = Description.new(server.address, result,
167
+ server.round_trip_time_averager.average_round_trip_time)
168
+ server.cluster.run_sdam_flow(server.description, new_description)
169
+ server.description
202
170
  end
203
171
 
204
172
  # Restarts the server monitor unless the current thread is alive.
@@ -217,29 +185,30 @@ module Mongo
217
185
  end
218
186
  end
219
187
 
220
- # @api private
221
- attr_reader :round_trip_time_averager
222
-
223
188
  private
224
189
 
190
+ def pre_stop
191
+ server.scan_semaphore.signal
192
+ end
193
+
225
194
  def ismaster
226
195
  @mutex.synchronize do
227
196
  if monitoring.monitoring?
228
197
  monitoring.started(
229
198
  Monitoring::SERVER_HEARTBEAT,
230
- Monitoring::Event::ServerHeartbeatStarted.new(description.address)
199
+ Monitoring::Event::ServerHeartbeatStarted.new(server.address)
231
200
  )
232
201
  end
233
202
 
234
- result, exc, rtt, average_rtt = round_trip_time_averager.measure do
203
+ result, exc, rtt, average_rtt = server.round_trip_time_averager.measure do
235
204
  connection.ismaster
236
205
  end
237
206
  if exc
238
- log_debug("Error running ismaster on #{description.address}: #{exc.message}")
207
+ log_debug("Error running ismaster on #{server.address}: #{exc.message}")
239
208
  if monitoring.monitoring?
240
209
  monitoring.failed(
241
210
  Monitoring::SERVER_HEARTBEAT,
242
- Monitoring::Event::ServerHeartbeatFailed.new(description.address, rtt, exc)
211
+ Monitoring::Event::ServerHeartbeatFailed.new(server.address, rtt, exc)
243
212
  )
244
213
  end
245
214
  result = {}
@@ -247,7 +216,7 @@ module Mongo
247
216
  if monitoring.monitoring?
248
217
  monitoring.succeeded(
249
218
  Monitoring::SERVER_HEARTBEAT,
250
- Monitoring::Event::ServerHeartbeatSucceeded.new(description.address, rtt)
219
+ Monitoring::Event::ServerHeartbeatSucceeded.new(server.address, rtt)
251
220
  )
252
221
  end
253
222
  end
@@ -258,12 +227,18 @@ module Mongo
258
227
  # @note If the system clock is set to a time in the past, this method
259
228
  # can sleep for a very long time.
260
229
  def throttle_scan_frequency!
261
- if @last_scan
262
- difference = (Time.now - @last_scan)
230
+ # Normally server.last_scan indicates when the previous scan
231
+ # completed, but if scan! is manually invoked repeatedly then
232
+ # server.last_scan won't be updated and multiple scans with no
233
+ # cooldown can be obtained. Guard against repeated direct scan!
234
+ # invocation also.
235
+ last_time = [server.last_scan, @scan_started_at].compact.max
236
+ if last_time
237
+ difference = (Time.now - last_time)
263
238
  throttle_time = (MIN_SCAN_FREQUENCY - difference)
264
239
  sleep(throttle_time) if throttle_time > 0
265
240
  end
266
- @last_scan = Time.now
241
+ @scan_started_at = Time.now
267
242
  end
268
243
  end
269
244
  end
@@ -228,6 +228,8 @@ module Mongo
228
228
  reply = Protocol::Message.deserialize(socket, Mongo::Protocol::Message::MAX_MESSAGE_SIZE).documents[0]
229
229
  set_compressor!(reply)
230
230
  reply
231
+ else
232
+ log_warn("Asked to handshake with #{address} but there was no app metadata provided")
231
233
  end
232
234
  rescue => e
233
235
  log_warn("Failed to handshake with #{address}: #{e.class}: #{e}")
@@ -417,19 +417,23 @@ module Mongo
417
417
  def filter_stale_servers(candidates, primary = nil)
418
418
  return candidates unless @max_staleness
419
419
 
420
+ # last_scan is filled out by the Monitor, and can be nil if a server
421
+ # had its description manually set rather than being normally updated
422
+ # via the SDAM flow. We don't handle the possibility of a nil
423
+ # last_scan here.
420
424
  if primary
421
425
  candidates.select do |server|
422
426
  validate_max_staleness_support!(server)
423
427
  staleness = (server.last_scan - server.last_write_date) -
424
428
  (primary.last_scan - primary.last_write_date) +
425
- server.heartbeat_frequency_seconds
429
+ server.cluster.heartbeat_interval
426
430
  staleness <= @max_staleness
427
431
  end
428
432
  else
429
433
  max_write_date = candidates.collect(&:last_write_date).max
430
434
  candidates.select do |server|
431
435
  validate_max_staleness_support!(server)
432
- staleness = max_write_date - server.last_write_date + server.heartbeat_frequency_seconds
436
+ staleness = max_write_date - server.last_write_date + server.cluster.heartbeat_interval
433
437
  staleness <= @max_staleness
434
438
  end
435
439
  end
@@ -461,10 +465,10 @@ module Mongo
461
465
 
462
466
  def validate_max_staleness_value!(cluster)
463
467
  if @max_staleness
464
- heartbeat_frequency_seconds = cluster.options[:heartbeat_frequency] || Server::Monitor::HEARTBEAT_FREQUENCY
468
+ heartbeat_interval = cluster.heartbeat_interval
465
469
  unless @max_staleness >= [
466
470
  SMALLEST_MAX_STALENESS_SECONDS,
467
- min_cluster_staleness = heartbeat_frequency_seconds + Cluster::IDLE_WRITE_PERIOD_SECONDS,
471
+ min_cluster_staleness = heartbeat_interval + Cluster::IDLE_WRITE_PERIOD_SECONDS,
468
472
  ].max
469
473
  msg = "`max_staleness` value (#{@max_staleness}) is too small - it must be at least " +
470
474
  "`Mongo::ServerSelector::SMALLEST_MAX_STALENESS_SECONDS` (#{ServerSelector::SMALLEST_MAX_STALENESS_SECONDS}) and (the cluster's heartbeat_frequency " +
@@ -492,7 +496,11 @@ module Mongo
492
496
  # @param [ Numeric ] time_remaining Maximum time to wait, in seconds.
493
497
  def wait_for_server_selection(cluster, time_remaining)
494
498
  if cluster.server_selection_semaphore
495
- cluster.server_selection_semaphore.wait(time_remaining)
499
+ # Since the semaphore may have been signaled between us checking
500
+ # the servers list earlier and the wait call below, we should not
501
+ # wait for the full remaining time - wait for up to 1 second, then
502
+ # recheck the state.
503
+ cluster.server_selection_semaphore.wait([time_remaining, 1].min)
496
504
  else
497
505
  if Lint.enabled?
498
506
  raise Error::LintError, 'Waiting for server selection without having a server selection semaphore'
data/lib/mongo/session.rb CHANGED
@@ -729,19 +729,6 @@ module Mongo
729
729
  end
730
730
  end
731
731
 
732
- # Add this session's id to a command document.
733
- #
734
- # @example
735
- # session.add_id!(cmd)
736
- #
737
- # @return [ Hash, BSON::Document ] The command document.
738
- #
739
- # @since 2.5.0
740
- # @api private
741
- def add_id!(command)
742
- command.merge!(lsid: session_id)
743
- end
744
-
745
732
  # Add the startTransaction field to a command document if applicable.
746
733
  #
747
734
  # @example
data/lib/mongo/srv.rb ADDED
@@ -0,0 +1,17 @@
1
+ # Copyright (C) 2019 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
+ require 'mongo/srv/result'
16
+ require 'mongo/srv/resolver'
17
+ require 'mongo/srv/monitor'