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
@@ -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'