mongo 2.7.2 → 2.8.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 (94) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -3
  4. data/lib/mongo/address.rb +17 -20
  5. data/lib/mongo/address/ipv4.rb +6 -3
  6. data/lib/mongo/address/ipv6.rb +6 -3
  7. data/lib/mongo/address/unix.rb +5 -2
  8. data/lib/mongo/auth.rb +15 -2
  9. data/lib/mongo/auth/cr/conversation.rb +4 -2
  10. data/lib/mongo/auth/ldap/conversation.rb +4 -2
  11. data/lib/mongo/auth/scram.rb +3 -7
  12. data/lib/mongo/auth/scram/conversation.rb +28 -19
  13. data/lib/mongo/auth/user.rb +45 -10
  14. data/lib/mongo/auth/x509/conversation.rb +4 -2
  15. data/lib/mongo/cluster.rb +9 -17
  16. data/lib/mongo/error.rb +2 -0
  17. data/lib/mongo/error/missing_password.rb +29 -0
  18. data/lib/mongo/error/operation_failure.rb +7 -3
  19. data/lib/mongo/error/parser.rb +2 -1
  20. data/lib/mongo/error/sdam_error_detection.rb +54 -0
  21. data/lib/mongo/operation/aggregate/command.rb +1 -16
  22. data/lib/mongo/operation/aggregate/op_msg.rb +1 -1
  23. data/lib/mongo/operation/collections_info.rb +2 -3
  24. data/lib/mongo/operation/delete/command.rb +2 -15
  25. data/lib/mongo/operation/delete/legacy.rb +1 -16
  26. data/lib/mongo/operation/explain/command.rb +1 -16
  27. data/lib/mongo/operation/explain/legacy.rb +1 -16
  28. data/lib/mongo/operation/find/command.rb +1 -16
  29. data/lib/mongo/operation/find/legacy.rb +1 -16
  30. data/lib/mongo/operation/get_more/command.rb +1 -16
  31. data/lib/mongo/operation/indexes/command.rb +1 -16
  32. data/lib/mongo/operation/indexes/legacy.rb +4 -16
  33. data/lib/mongo/operation/list_collections/command.rb +1 -16
  34. data/lib/mongo/operation/map_reduce/command.rb +1 -16
  35. data/lib/mongo/operation/parallel_scan/command.rb +1 -16
  36. data/lib/mongo/operation/result.rb +3 -0
  37. data/lib/mongo/operation/shared/executable.rb +4 -0
  38. data/lib/mongo/operation/shared/polymorphic_lookup.rb +1 -1
  39. data/lib/mongo/operation/shared/polymorphic_result.rb +8 -1
  40. data/lib/mongo/operation/shared/result/aggregatable.rb +0 -5
  41. data/lib/mongo/operation/update/command.rb +2 -15
  42. data/lib/mongo/operation/update/legacy.rb +1 -16
  43. data/lib/mongo/operation/users_info/command.rb +1 -16
  44. data/lib/mongo/retryable.rb +22 -10
  45. data/lib/mongo/server.rb +10 -1
  46. data/lib/mongo/server/app_metadata.rb +7 -2
  47. data/lib/mongo/server/connectable.rb +0 -6
  48. data/lib/mongo/server/connection.rb +86 -135
  49. data/lib/mongo/server/connection_base.rb +133 -0
  50. data/lib/mongo/server/connection_pool.rb +11 -24
  51. data/lib/mongo/server/connection_pool/queue.rb +41 -41
  52. data/lib/mongo/server/description.rb +1 -1
  53. data/lib/mongo/server/monitor.rb +4 -4
  54. data/lib/mongo/server/monitor/connection.rb +26 -7
  55. data/lib/mongo/server/pending_connection.rb +36 -0
  56. data/lib/mongo/server_selector/selectable.rb +9 -1
  57. data/lib/mongo/session.rb +0 -1
  58. data/lib/mongo/socket.rb +23 -6
  59. data/lib/mongo/socket/ssl.rb +11 -18
  60. data/lib/mongo/socket/tcp.rb +13 -14
  61. data/lib/mongo/socket/unix.rb +9 -27
  62. data/lib/mongo/uri.rb +1 -1
  63. data/lib/mongo/version.rb +1 -1
  64. data/spec/integration/auth_spec.rb +160 -0
  65. data/spec/integration/retryable_writes_spec.rb +55 -58
  66. data/spec/integration/sdam_error_handling_spec.rb +115 -0
  67. data/spec/mongo/address/ipv4_spec.rb +4 -0
  68. data/spec/mongo/address/ipv6_spec.rb +4 -0
  69. data/spec/mongo/auth/scram/conversation_spec.rb +6 -5
  70. data/spec/mongo/auth/scram/negotiation_spec.rb +25 -36
  71. data/spec/mongo/auth/scram_spec.rb +2 -2
  72. data/spec/mongo/auth/user_spec.rb +97 -0
  73. data/spec/mongo/client_construction_spec.rb +1 -1
  74. data/spec/mongo/error/operation_failure_spec.rb +125 -1
  75. data/spec/mongo/retryable_spec.rb +17 -8
  76. data/spec/mongo/server/connection_pool/queue_spec.rb +24 -10
  77. data/spec/mongo/server/connection_pool_spec.rb +30 -117
  78. data/spec/mongo/server/connection_spec.rb +147 -25
  79. data/spec/mongo/server/description_spec.rb +0 -14
  80. data/spec/mongo/server/monitor/connection_spec.rb +22 -0
  81. data/spec/mongo/server_selector_spec.rb +1 -0
  82. data/spec/mongo/server_spec.rb +6 -6
  83. data/spec/mongo/socket/ssl_spec.rb +48 -116
  84. data/spec/mongo/socket/tcp_spec.rb +22 -0
  85. data/spec/mongo/socket/unix_spec.rb +9 -9
  86. data/spec/mongo/socket_spec.rb +15 -3
  87. data/spec/spec_tests/server_selection_spec.rb +2 -0
  88. data/spec/support/client_registry.rb +8 -2
  89. data/spec/support/common_shortcuts.rb +20 -1
  90. data/spec/support/constraints.rb +10 -2
  91. data/spec/support/lite_constraints.rb +8 -0
  92. data/spec/support/spec_config.rb +9 -1
  93. metadata +14 -4
  94. metadata.gz.sig +0 -0
@@ -26,22 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
-
30
- # Execute the operation.
31
- #
32
- # @example
33
- # operation.execute(server)
34
- #
35
- # @param [ Mongo::Server ] server The server to send the operation to.
36
- #
37
- # @return [ Mongo::Operation::GetMore::Result ] The operation result.
38
- #
39
- # @since 2.5.2
40
- def execute(server)
41
- result = Result.new(dispatch_message(server))
42
- process_result(result, server)
43
- result.validate!
44
- end
29
+ include PolymorphicResult
45
30
 
46
31
  private
47
32
 
@@ -26,22 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
-
30
- # Execute the operation.
31
- #
32
- # @example
33
- # operation.execute(server)
34
- #
35
- # @param [ Mongo::Server ] server The server to send the operation to.
36
- #
37
- # @return [ Mongo::Operation::Indexes::Result ] The operation result.
38
- #
39
- # @since 2.5.2
40
- def execute(server)
41
- result = Result.new(dispatch_message(server))
42
- process_result(result, server)
43
- result.validate!
44
- end
29
+ include PolymorphicResult
45
30
 
46
31
  private
47
32
 
@@ -26,22 +26,6 @@ module Mongo
26
26
  include Executable
27
27
  include ReadPreferenceSupported
28
28
 
29
- # Execute the operation.
30
- #
31
- # @example
32
- # operation.execute(server)
33
- #
34
- # @param [ Mongo::Server ] server The server to send the operation to.
35
- #
36
- # @return [ Mongo::Operation::Indexes::Result ] The operation result.
37
- #
38
- # @since 2.5.2
39
- def execute(server)
40
- result = Operation::Result.new(dispatch_message(server))
41
- process_result(result, server)
42
- result.validate!
43
- end
44
-
45
29
  private
46
30
 
47
31
  def selector(server)
@@ -51,6 +35,10 @@ module Mongo
51
35
  def message(server)
52
36
  Protocol::Query.new(db_name, Index::COLLECTION, command(server), options(server))
53
37
  end
38
+
39
+ def result_class
40
+ Operation::Result
41
+ end
54
42
  end
55
43
  end
56
44
  end
@@ -26,22 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
-
30
- # Execute the operation.
31
- #
32
- # @example
33
- # operation.execute(server)
34
- #
35
- # @param [ Mongo::Server ] server The server to send the operation to.
36
- #
37
- # @return [ Mongo::Operation::ListCollections::Result ] The operation result.
38
- #
39
- # @since 2.5.2
40
- def execute(server)
41
- result = Result.new(dispatch_message(server))
42
- process_result(result, server)
43
- result.validate!
44
- end
29
+ include PolymorphicResult
45
30
 
46
31
  private
47
32
 
@@ -27,22 +27,7 @@ module Mongo
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
29
  include WriteConcernSupported
30
-
31
- # Execute the operation.
32
- #
33
- # @example
34
- # operation.execute(server)
35
- #
36
- # @param [ Mongo::Server ] server The server to send the operation to.
37
- #
38
- # @return [ Mongo::Operation::MapReduce::Result ] The operation result.
39
- #
40
- # @since 2.5.2
41
- def execute(server)
42
- result = Result.new(dispatch_message(server))
43
- process_result(result, server)
44
- result.validate!
45
- end
30
+ include PolymorphicResult
46
31
 
47
32
  private
48
33
 
@@ -26,22 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
-
30
- # Execute the operation.
31
- #
32
- # @example
33
- # operation.execute(server)
34
- #
35
- # @param [ Mongo::Server ] server The server to send the operation to.
36
- #
37
- # @return [ Mongo::Operation::ParallelScan::Result ] The operation result.
38
- #
39
- # @since 2.5.2
40
- def execute(server)
41
- result = Result.new(dispatch_message(server))
42
- process_result(result, server)
43
- result.validate!
44
- end
29
+ include PolymorphicResult
45
30
 
46
31
  private
47
32
 
@@ -79,6 +79,9 @@ module Mongo
79
79
  # @return [ Array<Protocol::Reply> ] replies The wrapped wire protocol replies.
80
80
  attr_reader :replies
81
81
 
82
+ def_delegators :parser,
83
+ :not_master?, :node_recovering?
84
+
82
85
  # Is the result acknowledged?
83
86
  #
84
87
  # @note On MongoDB 2.6 and higher all writes are acknowledged since the
@@ -45,6 +45,10 @@ module Mongo
45
45
 
46
46
  def process_result(result, server)
47
47
  server.update_cluster_time(result)
48
+ if result.not_master? || result.node_recovering?
49
+ server.unknown!
50
+ server.monitor.scan_semaphore.signal
51
+ end
48
52
  session.process(result) if session
49
53
  result
50
54
  end
@@ -25,7 +25,7 @@ module Mongo
25
25
  def polymorphic_class(base, name)
26
26
  bits = (base + "::#{name}").split('::')
27
27
  bits.reduce(Object) do |cls, name|
28
- cls.const_get(name)
28
+ cls.const_get(name, false)
29
29
  end
30
30
  end
31
31
  end
@@ -18,6 +18,9 @@ module Mongo
18
18
  # Shared behavior of instantiating a result class matching the
19
19
  # operation class.
20
20
  #
21
+ # This module must be included after Executable module because result_class
22
+ # is defined in both.
23
+ #
21
24
  # @api private
22
25
  module PolymorphicResult
23
26
  include PolymorphicLookup
@@ -25,7 +28,11 @@ module Mongo
25
28
  private
26
29
 
27
30
  def result_class
28
- polymorphic_class(self.class.name.sub(/::[^:]*$/, ''), :Result)
31
+ begin
32
+ polymorphic_class(self.class.name, :Result)
33
+ rescue NameError
34
+ polymorphic_class(self.class.name.sub(/::[^:]*$/, ''), :Result)
35
+ end
29
36
  end
30
37
  end
31
38
  end
@@ -68,8 +68,3 @@ module Mongo
68
68
  end
69
69
  end
70
70
  end
71
-
72
-
73
-
74
-
75
-
@@ -27,21 +27,8 @@ module Mongo
27
27
  include Limited
28
28
  include WriteConcernSupported
29
29
  include BypassDocumentValidation
30
-
31
- # Execute the operation.
32
- #
33
- # @example
34
- # operation.execute(server)
35
- #
36
- # @param [ Mongo::Server ] server The server to send the operation to.
37
- #
38
- # @return [ Mongo::Operation::Update::Result ] The operation result.
39
- #
40
- # @since 2.5.2
41
- def execute(server)
42
- result = Result.new(dispatch_message(server))
43
- process_result(result, server)
44
- end
30
+ include ExecutableNoValidate
31
+ include PolymorphicResult
45
32
 
46
33
  private
47
34
 
@@ -26,22 +26,7 @@ module Mongo
26
26
  class Legacy
27
27
  include Specifiable
28
28
  include Executable
29
-
30
- # Execute the operation.
31
- #
32
- # @example
33
- # operation.execute(server)
34
- #
35
- # @param [ Mongo::Server ] server The server to send the operation to.
36
- #
37
- # @return [ Mongo::Operation::Update::Result ] The operation result.
38
- #
39
- # @since 2.5.2
40
- def execute(server)
41
- result = Result.new(dispatch_message(server))
42
- process_result(result, server)
43
- result.validate!
44
- end
29
+ include PolymorphicResult
45
30
 
46
31
  private
47
32
 
@@ -26,22 +26,7 @@ module Mongo
26
26
  include Executable
27
27
  include Limited
28
28
  include ReadPreferenceSupported
29
-
30
- # Execute the operation.
31
- #
32
- # @example
33
- # operation.execute(server)
34
- #
35
- # @param [ Mongo::Server ] server The server to send the operation to.
36
- #
37
- # @return [ Mongo::Operation::UsersInfo::Result ] The operation result.
38
- #
39
- # @since 2.5.2
40
- def execute(server)
41
- result = Result.new(dispatch_message(server))
42
- process_result(result, server)
43
- result.validate!
44
- end
29
+ include PolymorphicResult
45
30
 
46
31
  private
47
32
 
@@ -42,18 +42,22 @@ module Mongo
42
42
  attempt += 1
43
43
  yield
44
44
  rescue Error::SocketError, Error::SocketTimeoutError => e
45
- raise(e) if attempt > cluster.max_read_retries || (session && session.in_transaction?)
45
+ if attempt > cluster.max_read_retries || (session && session.in_transaction?)
46
+ raise
47
+ end
46
48
  log_retry(e)
47
49
  cluster.scan!(false)
48
50
  retry
49
51
  rescue Error::OperationFailure => e
50
52
  if cluster.sharded? && e.retryable? && !(session && session.in_transaction?)
51
- raise(e) if attempt > cluster.max_read_retries
53
+ if attempt > cluster.max_read_retries
54
+ raise
55
+ end
52
56
  log_retry(e)
53
57
  sleep(cluster.read_retry_interval)
54
58
  retry
55
59
  else
56
- raise e
60
+ raise
57
61
  end
58
62
  end
59
63
  end
@@ -141,10 +145,14 @@ module Mongo
141
145
  txn_num = session.in_transaction? ? session.txn_num : session.next_txn_num
142
146
  yield(server, txn_num, false)
143
147
  rescue Error::SocketError, Error::SocketTimeoutError => e
144
- raise e if session.in_transaction? && !ending_transaction
148
+ if session.in_transaction? && !ending_transaction
149
+ raise
150
+ end
145
151
  retry_write(e, txn_num, &block)
146
152
  rescue Error::OperationFailure => e
147
- raise e if (session.in_transaction? && !ending_transaction) || !e.write_retryable?
153
+ if (session.in_transaction? && !ending_transaction) || !e.write_retryable?
154
+ raise
155
+ end
148
156
  retry_write(e, txn_num, &block)
149
157
  end
150
158
  end
@@ -167,17 +175,19 @@ module Mongo
167
175
  end
168
176
 
169
177
  def retry_write(original_error, txn_num, &block)
170
- cluster.scan!(false)
178
+ # We do not request a scan of the cluster here, because error handling
179
+ # for the error which triggered the retry should have updated the
180
+ # server description and/or topology as necessary (specifically,
181
+ # a socket error or a not master error should have marked the respective
182
+ # server unknown). Here we just need to wait for server selection.
171
183
  server = cluster.next_primary
172
184
  raise original_error unless (server.retry_writes? && txn_num)
173
185
  log_retry(original_error)
174
186
  yield(server, txn_num, true)
175
187
  rescue Error::SocketError, Error::SocketTimeoutError => e
176
- cluster.scan!(false)
177
188
  raise e
178
189
  rescue Error::OperationFailure => e
179
190
  raise original_error unless e.write_retryable?
180
- cluster.scan!(false)
181
191
  raise e
182
192
  rescue
183
193
  raise original_error
@@ -193,13 +203,15 @@ module Mongo
193
203
  yield(server || cluster.next_primary)
194
204
  rescue Error::OperationFailure => e
195
205
  server = nil
196
- raise(e) if attempt > Cluster::MAX_WRITE_RETRIES
206
+ if attempt > Cluster::MAX_WRITE_RETRIES
207
+ raise
208
+ end
197
209
  if e.write_retryable? && !(session && session.in_transaction?)
198
210
  log_retry(e)
199
211
  cluster.scan!(false)
200
212
  retry
201
213
  else
202
- raise(e)
214
+ raise
203
215
  end
204
216
  end
205
217
  end
@@ -67,6 +67,7 @@ module Mongo
67
67
  start_monitoring
68
68
  end
69
69
  @connected = true
70
+ @pool_lock = Mutex.new
70
71
  end
71
72
 
72
73
  # @return [ String ] The configured address for the server.
@@ -280,7 +281,13 @@ module Mongo
280
281
  #
281
282
  # @since 2.0.0
282
283
  def pool
283
- @pool ||= cluster.pool(self)
284
+ @pool_lock.synchronize do
285
+ @pool ||= begin
286
+ ConnectionPool.new(options) do |generation|
287
+ Connection.new(self, options.merge(generation: generation))
288
+ end
289
+ end
290
+ end
284
291
  end
285
292
 
286
293
  # Determine if the provided tags are a subset of the server's tags.
@@ -401,6 +408,8 @@ end
401
408
 
402
409
  require 'mongo/server/app_metadata'
403
410
  require 'mongo/server/connectable'
411
+ require 'mongo/server/connection_base'
412
+ require 'mongo/server/pending_connection'
404
413
  require 'mongo/server/connection'
405
414
  require 'mongo/server/connection_pool'
406
415
  require 'mongo/server/context'
@@ -32,14 +32,19 @@ module Mongo
32
32
 
33
33
  # The max application name byte size.
34
34
  #
35
- # @ since 2.4.0
35
+ # @since 2.4.0
36
36
  MAX_APP_NAME_SIZE = 128.freeze
37
37
 
38
38
  # The driver name.
39
39
  #
40
- # @ since 2.4.0
40
+ # @since 2.4.0
41
41
  DRIVER_NAME = 'mongo-ruby-driver'
42
42
 
43
+ # Option keys that affect auth mechanism negotiation.
44
+ #
45
+ # @api private
46
+ AUTH_OPTION_KEYS = [:user, :auth_source, :auth_mech].freeze
47
+
43
48
  # Instantiate the new AppMetadata object.
44
49
  #
45
50
  # @api private
@@ -34,12 +34,6 @@ module Mongo
34
34
  # Will be removed in driver version 3.0.
35
35
  TIMEOUT = 5.freeze
36
36
 
37
- # @return [ Mongo::Address ] address The address to connect to.
38
- attr_reader :address
39
-
40
- # @return [ Hash ] options The passed in options.
41
- attr_reader :options
42
-
43
37
  # @return [ Integer ] pid The process id when the connection was created.
44
38
  attr_reader :pid
45
39