mongo 2.11.0.rc0 → 2.11.0

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 (154) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -0
  5. data/lib/mongo/auth.rb +11 -2
  6. data/lib/mongo/auth/cr/conversation.rb +1 -1
  7. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  8. data/lib/mongo/auth/scram/conversation.rb +4 -1
  9. data/lib/mongo/auth/user.rb +15 -1
  10. data/lib/mongo/auth/user/view.rb +10 -4
  11. data/lib/mongo/auth/x509.rb +11 -1
  12. data/lib/mongo/auth/x509/conversation.rb +15 -6
  13. data/lib/mongo/background_thread.rb +28 -13
  14. data/lib/mongo/client.rb +23 -15
  15. data/lib/mongo/collection/view/change_stream.rb +5 -1
  16. data/lib/mongo/collection/view/readable.rb +5 -2
  17. data/lib/mongo/collection/view/writable.rb +3 -1
  18. data/lib/mongo/cursor/builder/get_more_command.rb +4 -1
  19. data/lib/mongo/cursor/builder/kill_cursors_command.rb +16 -5
  20. data/lib/mongo/cursor/builder/op_get_more.rb +2 -2
  21. data/lib/mongo/cursor/builder/op_kill_cursors.rb +17 -5
  22. data/lib/mongo/error/operation_failure.rb +3 -3
  23. data/lib/mongo/monitoring/command_log_subscriber.rb +5 -3
  24. data/lib/mongo/monitoring/event/command_started.rb +13 -3
  25. data/lib/mongo/monitoring/publishable.rb +4 -2
  26. data/lib/mongo/operation/create_user/command.rb +1 -0
  27. data/lib/mongo/operation/remove_user/command.rb +1 -0
  28. data/lib/mongo/operation/update_user/command.rb +1 -0
  29. data/lib/mongo/protocol/get_more.rb +2 -1
  30. data/lib/mongo/protocol/kill_cursors.rb +6 -13
  31. data/lib/mongo/protocol/serializers.rb +10 -4
  32. data/lib/mongo/retryable.rb +1 -1
  33. data/lib/mongo/server/connection.rb +6 -2
  34. data/lib/mongo/server/connection_base.rb +2 -1
  35. data/lib/mongo/server/monitor.rb +1 -1
  36. data/lib/mongo/server/pending_connection.rb +6 -0
  37. data/lib/mongo/socket/ssl.rb +1 -1
  38. data/lib/mongo/uri.rb +5 -41
  39. data/lib/mongo/version.rb +1 -1
  40. data/mongo.gemspec +11 -2
  41. data/spec/README.md +105 -9
  42. data/spec/USERS.md +72 -0
  43. data/spec/integration/auth_spec.rb +20 -6
  44. data/spec/integration/client_construction_spec.rb +3 -1
  45. data/spec/integration/client_options_spec.rb +437 -0
  46. data/spec/integration/command_monitoring_spec.rb +4 -1
  47. data/spec/integration/connection_pool_populator_spec.rb +4 -0
  48. data/spec/integration/connection_spec.rb +4 -2
  49. data/spec/integration/cursor_reaping_spec.rb +1 -1
  50. data/spec/integration/get_more_spec.rb +32 -0
  51. data/spec/integration/retryable_errors_spec.rb +99 -0
  52. data/spec/integration/retryable_writes_errors_spec.rb +11 -10
  53. data/spec/lite_spec_helper.rb +2 -1
  54. data/spec/mongo/auth/scram_spec.rb +1 -0
  55. data/spec/mongo/auth/user/view_spec.rb +102 -1
  56. data/spec/mongo/auth/user_spec.rb +56 -15
  57. data/spec/mongo/auth/x509_spec.rb +31 -1
  58. data/spec/mongo/bulk_write_spec.rb +2 -2
  59. data/spec/mongo/collection/view/change_stream_spec.rb +2 -2
  60. data/spec/mongo/collection/view/readable_spec.rb +8 -4
  61. data/spec/mongo/cursor/builder/get_more_command_spec.rb +4 -2
  62. data/spec/mongo/cursor/builder/op_get_more_spec.rb +4 -2
  63. data/spec/mongo/cursor_spec.rb +3 -3
  64. data/spec/mongo/retryable_spec.rb +31 -52
  65. data/spec/mongo/server/connection_auth_spec.rb +3 -0
  66. data/spec/mongo/server/connection_pool_spec.rb +4 -0
  67. data/spec/mongo/server/connection_spec.rb +12 -4
  68. data/spec/mongo/server/monitor_spec.rb +19 -1
  69. data/spec/mongo/socket/ssl_spec.rb +1 -1
  70. data/spec/mongo/uri/srv_protocol_spec.rb +0 -13
  71. data/spec/mongo/uri_option_parsing_spec.rb +0 -8
  72. data/spec/mongo/uri_spec.rb +6 -20
  73. data/spec/runners/connection_string.rb +116 -0
  74. data/spec/runners/read_write_concern_document.rb +67 -0
  75. data/spec/spec_tests/change_streams_spec.rb +17 -2
  76. data/spec/spec_tests/connection_string_spec.rb +2 -59
  77. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +3 -3
  78. data/spec/spec_tests/data/change_streams/change-streams.yml +88 -20
  79. data/spec/spec_tests/data/cmap/connection-must-have-id.yml +6 -0
  80. data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +6 -0
  81. data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +3 -0
  82. data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +3 -0
  83. data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +3 -0
  84. data/spec/spec_tests/data/cmap/pool-checkin.yml +1 -0
  85. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +2 -0
  86. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +5 -0
  87. data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +3 -0
  88. data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +4 -0
  89. data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +4 -0
  90. data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +2 -0
  91. data/spec/spec_tests/data/cmap/pool-create-max-size.yml +15 -0
  92. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +4 -0
  93. data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +31 -1
  94. data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +5 -0
  95. data/spec/spec_tests/data/read_write_concern/connection-string/read-concern.yml +32 -0
  96. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +82 -0
  97. data/spec/spec_tests/data/read_write_concern/document/read-concern.yml +37 -0
  98. data/spec/spec_tests/data/read_write_concern/document/write-concern.yml +100 -0
  99. data/spec/spec_tests/data/retryable_reads/aggregate-merge.yml +39 -0
  100. data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +1 -1
  101. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +2 -2
  102. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +1 -1
  103. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +2 -2
  104. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +1 -1
  105. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +2 -2
  106. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +1 -1
  107. data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +1 -1
  108. data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +1 -1
  109. data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +1 -1
  110. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +1 -1
  111. data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +1 -1
  112. data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +1 -1
  113. data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +1 -1
  114. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +1 -1
  115. data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +1 -1
  116. data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +1 -1
  117. data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +1 -1
  118. data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +1 -1
  119. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +1 -1
  120. data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +1 -1
  121. data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +1 -1
  122. data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +1 -1
  123. data/spec/spec_tests/data/transactions/read-concern.yml +6 -6
  124. data/spec/spec_tests/data/transactions/transaction-options-repl.yml +117 -0
  125. data/spec/spec_tests/data/transactions/transaction-options.yml +14 -121
  126. data/spec/spec_tests/data/transactions/write-concern.yml +3 -0
  127. data/spec/spec_tests/data/transactions_api/transaction-options.yml +11 -12
  128. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +17 -7
  129. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +8 -0
  130. data/spec/spec_tests/read_write_concern_document_spec.rb +74 -0
  131. data/spec/spec_tests/retryable_reads_spec.rb +32 -1
  132. data/spec/spec_tests/uri_options_spec.rb +4 -2
  133. data/spec/support/auth.rb +5 -14
  134. data/spec/support/certificates/client-x509.crt +78 -0
  135. data/spec/support/certificates/client-x509.key +27 -0
  136. data/spec/support/certificates/client-x509.pem +105 -0
  137. data/spec/support/change_streams.rb +8 -11
  138. data/spec/support/client_registry.rb +26 -12
  139. data/spec/support/cluster_tools.rb +2 -2
  140. data/spec/support/cmap.rb +11 -7
  141. data/spec/support/command_monitoring.rb +8 -8
  142. data/spec/support/connection_string.rb +56 -28
  143. data/spec/support/constraints.rb +8 -0
  144. data/spec/support/crud/spec.rb +5 -8
  145. data/spec/support/event_subscriber.rb +7 -0
  146. data/spec/support/gridfs.rb +4 -7
  147. data/spec/support/server_discovery_and_monitoring.rb +3 -8
  148. data/spec/support/server_selection.rb +4 -9
  149. data/spec/support/server_selection_rtt.rb +4 -7
  150. data/spec/support/spec_config.rb +47 -19
  151. data/spec/support/spec_setup.rb +5 -0
  152. data/spec/support/utils.rb +46 -8
  153. metadata +637 -597
  154. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7c88c591ffb30fe10134db69727372a4d1c3801a11dce59804ebe53d475d08f
4
- data.tar.gz: 16ce4f803cd46df9e0bc6948048fc4c0ea5356d437fbf75b149d38cd872ccca1
3
+ metadata.gz: d27047092172489df2f36b02e09050990a7aae2685a055bf4a30d33a43b86325
4
+ data.tar.gz: 0f14e016a1dbae9ccda55d77927a773d58a10967b959b9480b052c2df9410386
5
5
  SHA512:
6
- metadata.gz: eb30b7789af0a8816ce50e4b5c3be68e0b0a6f3a0b2da8d4c13a6f6bc8ad826b6a6b505e99df369ed49b24543baa28ff08db655ce3701c1fd2f13b55d4bb9374
7
- data.tar.gz: 7490c21d89f2b2c88aaa69d8203973869c409c637c0a212cb2d3cd2783ca258cd6a2df6729375e39894303b39541fd0296faee7c691d1b3e4c3553f6c6169385
6
+ metadata.gz: 3cf2e4bfd5860003b7131c72fae1b58a0a56906a73d67e9e08c465cd5cf0b79f99af431e55597733f3baf9d68a9617cec47647d4bb7b9c8e84eedeeff96509b9
7
+ data.tar.gz: 190be385cbcfdae0293448281010b8d6c4ca785b37236fe57362921eaeb7cfdb5115dd0159e51622946b97170fa105a375fd0a73ceb4600b268e599aa687dcf1
Binary file
data.tar.gz.sig CHANGED
Binary file
data/Rakefile CHANGED
@@ -29,6 +29,7 @@ namespace :spec do
29
29
  task :prepare do
30
30
  $: << File.join(File.dirname(__FILE__), 'spec')
31
31
 
32
+ require 'support/utils'
32
33
  require 'support/spec_setup'
33
34
  SpecSetup.new.run
34
35
  end
@@ -40,6 +41,7 @@ namespace :spec do
40
41
  # Since this task is usually used for troubleshooting of test suite
41
42
  # configuration, leave driver log level at the default of debug to
42
43
  # have connection diagnostics printed during handshakes and such.
44
+ require 'support/utils'
43
45
  require 'support/spec_config'
44
46
  require 'support/client_registry'
45
47
  SpecConfig.instance.print_summary
@@ -109,9 +109,10 @@ module Mongo
109
109
  # @param [ Mongo::Auth::User ] user The unauthorized user.
110
110
  # @param [ String ] used_mechanism Auth mechanism actually used for
111
111
  # authentication. This is a full string like SCRAM-SHA-256.
112
+ # @param [ String ] message The error message returned by the server.
112
113
  #
113
114
  # @since 2.0.0
114
- def initialize(user, used_mechanism = nil)
115
+ def initialize(user, used_mechanism: nil, message: nil)
115
116
  specified_mechanism = if user.mechanism
116
117
  " (mechanism: #{user.mechanism})"
117
118
  else
@@ -122,7 +123,15 @@ module Mongo
122
123
  else
123
124
  ''
124
125
  end
125
- msg = "User #{user.name}#{specified_mechanism} is not authorized to access #{user.database}#{used_mechanism}"
126
+ used_user = if user.mechanism == :mongodb_x509
127
+ 'Client certificate'
128
+ else
129
+ "User #{user.name}"
130
+ end
131
+ msg = "#{used_user}#{specified_mechanism} is not authorized to access #{user.database} (auth source: #{user.auth_source})#{used_mechanism}"
132
+ if message
133
+ msg += ': ' + message
134
+ end
126
135
  super(msg)
127
136
  end
128
137
  end
@@ -131,7 +131,7 @@ module Mongo
131
131
 
132
132
  def validate!(reply)
133
133
  if reply.documents[0][Operation::Result::OK] != 1
134
- raise Unauthorized.new(user, MECHANISM)
134
+ raise Unauthorized.new(user, used_mechanism: MECHANISM)
135
135
  end
136
136
  @nonce = reply.documents[0][Auth::NONCE]
137
137
  @reply = reply
@@ -98,7 +98,7 @@ module Mongo
98
98
 
99
99
  def validate!(reply)
100
100
  if reply.documents[0][Operation::Result::OK] != 1
101
- raise Unauthorized.new(user, MECHANISM)
101
+ raise Unauthorized.new(user, used_mechanism: MECHANISM)
102
102
  end
103
103
  @reply = reply
104
104
  end
@@ -519,7 +519,10 @@ module Mongo
519
519
 
520
520
  def validate!(reply)
521
521
  if reply.documents[0][Operation::Result::OK] != 1
522
- raise Unauthorized.new(user, full_mechanism)
522
+ raise Unauthorized.new(user,
523
+ used_mechanism: full_mechanism,
524
+ message: reply.documents[0]['errmsg'],
525
+ )
523
526
  end
524
527
  @reply = reply
525
528
  end
@@ -159,7 +159,7 @@ module Mongo
159
159
  # @since 2.0.0
160
160
  def initialize(options)
161
161
  @database = options[:database] || Database::ADMIN
162
- @auth_source = options[:auth_source] || @database
162
+ @auth_source = options[:auth_source] || self.class.default_auth_source(options)
163
163
  @name = options[:user]
164
164
  @password = options[:password] || options[:pwd]
165
165
  @mechanism = options[:auth_mech]
@@ -205,6 +205,20 @@ module Mongo
205
205
  #
206
206
  # @return [ String ] The client key for the user.
207
207
  attr_reader :client_key
208
+
209
+ # Generate default auth source based on the URI and options
210
+ #
211
+ # @api private
212
+ def self.default_auth_source(options)
213
+ case options[:auth_mech]
214
+ when :gssapi, :mongodb_x509
215
+ '$external'
216
+ when :plain
217
+ options[:database] || '$external'
218
+ else
219
+ options[:database] || Database::ADMIN
220
+ end
221
+ end
208
222
  end
209
223
  end
210
224
  end
@@ -37,6 +37,7 @@ module Mongo
37
37
  # @param [ Hash ] options The user options.
38
38
  #
39
39
  # @option options [ Session ] :session The session to use for the operation.
40
+ # @option options [ Hash ] :write_concern The write concern options.
40
41
  #
41
42
  # @return [ Result ] The command response.
42
43
  #
@@ -47,7 +48,8 @@ module Mongo
47
48
  Operation::CreateUser.new(
48
49
  user: user,
49
50
  db_name: database.name,
50
- session: session
51
+ session: session,
52
+ write_concern: options[:write_concern] && WriteConcern.get(options[:write_concern]),
51
53
  ).execute(next_primary(nil, session))
52
54
  end
53
55
  end
@@ -73,6 +75,7 @@ module Mongo
73
75
  # @param [ Hash ] options The options for the remove operation.
74
76
  #
75
77
  # @option options [ Session ] :session The session to use for the operation.
78
+ # @option options [ Hash ] :write_concern The write concern options.
76
79
  #
77
80
  # @return [ Result ] The command response.
78
81
  #
@@ -82,7 +85,8 @@ module Mongo
82
85
  Operation::RemoveUser.new(
83
86
  user_name: name,
84
87
  db_name: database.name,
85
- session: session
88
+ session: session,
89
+ write_concern: options[:write_concern] && WriteConcern.get(options[:write_concern]),
86
90
  ).execute(next_primary(nil, session))
87
91
  end
88
92
  end
@@ -96,6 +100,7 @@ module Mongo
96
100
  # @param [ Hash ] options The user options.
97
101
  #
98
102
  # @option options [ Session ] :session The session to use for the operation.
103
+ # @option options [ Hash ] :write_concern The write concern options.
99
104
  #
100
105
  # @return [ Result ] The response.
101
106
  #
@@ -106,7 +111,8 @@ module Mongo
106
111
  Operation::UpdateUser.new(
107
112
  user: user,
108
113
  db_name: database.name,
109
- session: session
114
+ session: session,
115
+ write_concern: options[:write_concern] && WriteConcern.get(options[:write_concern]),
110
116
  ).execute(next_primary(nil, session))
111
117
  end
112
118
  end
@@ -121,7 +127,7 @@ module Mongo
121
127
  #
122
128
  # @option options [ Session ] :session The session to use for the operation.
123
129
  #
124
- # @return [ Hash ] A document containing information on a particular user.
130
+ # @return [ Array ] An array wrapping a document containing information on a particular user.
125
131
  #
126
132
  # @since 2.1.0
127
133
  def info(name, options = {})
@@ -17,7 +17,7 @@ require 'mongo/auth/x509/conversation'
17
17
  module Mongo
18
18
  module Auth
19
19
 
20
- # Defines behavior for x.509 authentication.
20
+ # Defines behavior for X.509 authentication.
21
21
  #
22
22
  # @since 2.0.0
23
23
  class X509
@@ -39,6 +39,16 @@ module Mongo
39
39
  #
40
40
  # @since 2.0.0
41
41
  def initialize(user)
42
+ # The only valid database for X.509 authentication is $external.
43
+ if user.auth_source != '$external'
44
+ user_name_msg = if user.name
45
+ " #{user.name}"
46
+ else
47
+ ''
48
+ end
49
+ raise Auth::InvalidConfiguration, "User#{user_name_msg} specifies auth source '#{user.auth_source}', but the only valid auth source for X.509 is '$external'"
50
+ end
51
+
42
52
  @user = user
43
53
  end
44
54
 
@@ -16,7 +16,7 @@ module Mongo
16
16
  module Auth
17
17
  class X509
18
18
 
19
- # Defines behavior around a single x.509 conversation between the
19
+ # Defines behavior around a single X.509 conversation between the
20
20
  # client and server.
21
21
  #
22
22
  # @since 2.0.0
@@ -34,7 +34,7 @@ module Mongo
34
34
  # @return [ User ] user The user for the conversation.
35
35
  attr_reader :user
36
36
 
37
- # Finalize the x.509 conversation. This is meant to be iterated until
37
+ # Finalize the X.509 conversation. This is meant to be iterated until
38
38
  # the provided reply indicates the conversation is finished.
39
39
  #
40
40
  # @example Finalize the conversation.
@@ -50,7 +50,7 @@ module Mongo
50
50
  validate!(reply)
51
51
  end
52
52
 
53
- # Start the x.509 conversation. This returns the first message that
53
+ # Start the X.509 conversation. This returns the first message that
54
54
  # needs to be sent to the server.
55
55
  #
56
56
  # @example Start the conversation.
@@ -58,7 +58,7 @@ module Mongo
58
58
  #
59
59
  # @param [ Mongo::Server::Connection ] connection The connection being authenticated.
60
60
  #
61
- # @return [ Protocol::Query ] The first x.509 conversation message.
61
+ # @return [ Protocol::Query ] The first X.509 conversation message.
62
62
  #
63
63
  # @since 2.0.0
64
64
  def start(connection = nil)
@@ -66,7 +66,16 @@ module Mongo
66
66
  login[:user] = user.name if user.name
67
67
  if connection && connection.features.op_msg_enabled?
68
68
  selector = login
69
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
69
+ # The only valid database for X.509 authentication is $external.
70
+ if user.auth_source != '$external'
71
+ user_name_msg = if user.name
72
+ " #{user.name}"
73
+ else
74
+ ''
75
+ end
76
+ raise Auth::InvalidConfiguration, "User#{user_name_msg} specifies auth source '#{user.auth_source}', but the only valid auth source for X.509 is '$external'"
77
+ end
78
+ selector[Protocol::Msg::DATABASE_IDENTIFIER] = '$external'
70
79
  cluster_time = connection.mongos? && connection.cluster_time
71
80
  selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
72
81
  Protocol::Msg.new([], {}, selector)
@@ -96,7 +105,7 @@ module Mongo
96
105
 
97
106
  def validate!(reply)
98
107
  if reply.documents[0][Operation::Result::OK] != 1
99
- raise Unauthorized.new(user, MECHANISM)
108
+ raise Unauthorized.new(user, used_mechanism: MECHANISM)
100
109
  end
101
110
  @reply = reply
102
111
  end
@@ -30,6 +30,14 @@ module Mongo
30
30
  #
31
31
  # @api public for backwards compatibility only
32
32
  def run!
33
+ if @stop_requested && @thread
34
+ wait_for_stop
35
+ if @thread.alive?
36
+ log_warn("Starting a new background thread in #{self}, but the previous background thread is still running")
37
+ @thread = nil
38
+ end
39
+ @stop_requested = false
40
+ end
33
41
  if running?
34
42
  @thread
35
43
  else
@@ -81,6 +89,25 @@ module Mongo
81
89
  # the middle of an operation.
82
90
  @thread.kill
83
91
 
92
+ wait_for_stop
93
+ end
94
+
95
+ private
96
+
97
+ def start!
98
+ @thread = Thread.new do
99
+ catch(:done) do
100
+ until @stop_requested
101
+ do_work
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # Waits for the thread to die, with a timeout.
108
+ #
109
+ # Returns true if the thread died, false otherwise.
110
+ def wait_for_stop
84
111
  # Wait for the thread to die. This is important in order to reliably
85
112
  # clean up resources like connections knowing that no background
86
113
  # thread will reconnect because it is still working.
@@ -106,23 +133,11 @@ module Mongo
106
133
  false
107
134
  else
108
135
  @thread = nil
136
+ @stop_requested = false
109
137
  true
110
138
  end
111
139
  end
112
140
 
113
- private
114
-
115
- # @return [ Thread ] The created Thread instance.
116
- def start!
117
- @thread = Thread.new do
118
- catch(:done) do
119
- until @stop_requested
120
- do_work
121
- end
122
- end
123
- end
124
- end
125
-
126
141
  # Override this method to do the work in the background thread.
127
142
  def do_work
128
143
  end
@@ -363,7 +363,8 @@ module Mongo
363
363
  # @option options [ Hash ] :write Deprecated. Equivalent to :write_concern
364
364
  # option.
365
365
  # @option options [ Hash ] :write_concern The write concern options.
366
- # Can be :w => Integer|String, :fsync => Boolean, :j => Boolean.
366
+ # Can be :w => Integer|String, :wtimeout => Integer (in milliseconds),
367
+ # :j => Boolean, :fsync => Boolean.
367
368
  # @option options [ Integer ] :zlib_compression_level The Zlib compression level to use, if using compression.
368
369
  # See Ruby's Zlib module for valid levels.
369
370
  # @option options [ Hash ] :resolv_options For internal driver use only.
@@ -371,11 +372,7 @@ module Mongo
371
372
  #
372
373
  # @since 2.0.0
373
374
  def initialize(addresses_or_uri, options = nil)
374
- if options
375
- options = options.dup
376
- else
377
- options = {}
378
- end
375
+ options = options ? options.dup : {}
379
376
 
380
377
  srv_uri = nil
381
378
  if addresses_or_uri.is_a?(::String)
@@ -401,18 +398,12 @@ module Mongo
401
398
  @srv_records = nil
402
399
  end
403
400
 
404
- unless options[:retry_reads] == false
405
- options[:retry_reads] = true
406
- end
407
- unless options[:retry_writes] == false
408
- options[:retry_writes] = true
409
- end
410
-
411
401
  # Special handling for sdam_proc as it is only used during client
412
402
  # construction
413
403
  sdam_proc = options.delete(:sdam_proc)
414
404
 
415
- @options = validate_new_options!(Database::DEFAULT_OPTIONS.merge(options))
405
+ options = default_options(options).merge(options)
406
+ @options = validate_new_options!(options)
416
407
  =begin WriteConcern object support
417
408
  if @options[:write_concern].is_a?(WriteConcern::Base)
418
409
  # Cache the instance so that we do not needlessly reconstruct it.
@@ -814,6 +805,23 @@ module Mongo
814
805
 
815
806
  private
816
807
 
808
+ # Generate default client options based on the URI and options
809
+ # passed into the Client constructor.
810
+ def default_options(options)
811
+ Database::DEFAULT_OPTIONS.dup.tap do |default_options|
812
+ if options[:auth_mech] || options[:user]
813
+ default_options[:auth_source] = Auth::User.default_auth_source(options)
814
+ end
815
+
816
+ if options[:auth_mech] == :gssapi
817
+ default_options[:auth_mech_properties] = { service_name: 'mongodb' }
818
+ end
819
+
820
+ default_options[:retry_reads] = true
821
+ default_options[:retry_writes] = true
822
+ end
823
+ end
824
+
817
825
  # If options[:session] is set, validates that session and returns it.
818
826
  # If deployment supports sessions, creates a new session and returns it.
819
827
  # The session is implicit unless options[:implicit] is given.
@@ -914,7 +922,7 @@ module Mongo
914
922
  raise Mongo::Auth::InvalidConfiguration.new('password is not supported for mongodb_x509')
915
923
  end
916
924
 
917
- if ![:external, nil].include?(auth_source) && [:gssapi, :mongodb_x509].include?(auth_mech)
925
+ if !['$external', nil].include?(auth_source) && [:gssapi, :mongodb_x509].include?(auth_mech)
918
926
  raise Mongo::Auth::InvalidConfiguration.new("#{auth_source} is an invalid auth source for #{auth_mech}; valid options are $external and nil")
919
927
  end
920
928
 
@@ -296,7 +296,11 @@ module Mongo
296
296
  end
297
297
 
298
298
  def change_doc
299
- { fullDocument: ( @options[:full_document] || FULL_DOCUMENT_DEFAULT ) }.tap do |doc|
299
+ {}.tap do |doc|
300
+ if @options[:full_document]
301
+ doc[:fullDocument] = @options[:full_document]
302
+ end
303
+
300
304
  if resuming?
301
305
  # We have a resume token once we retrieved any documents.
302
306
  # However, if the first getMore fails and the user didn't pass
@@ -244,6 +244,9 @@ module Mongo
244
244
  #
245
245
  # @since 2.0.0
246
246
  def distinct(field_name, opts = {})
247
+ if field_name.nil?
248
+ raise ArgumentError, 'Field name for distinct operation must be not nil'
249
+ end
247
250
  cmd = { :distinct => collection.name,
248
251
  :key => field_name.to_s,
249
252
  :query => filter }
@@ -602,7 +605,7 @@ module Mongo
602
605
  cmd.execute(server).cursor_ids.map do |cursor_id|
603
606
  result = if server.features.find_command_enabled?
604
607
  Operation::GetMore.new({
605
- :selector => {:getMore => cursor_id,
608
+ :selector => {:getMore => BSON::Int64.new(cursor_id),
606
609
  :collection => collection.name},
607
610
  :db_name => database.name,
608
611
  :session => session,
@@ -610,7 +613,7 @@ module Mongo
610
613
  else
611
614
  Operation::GetMore.new({
612
615
  :to_return => 0,
613
- :cursor_id => cursor_id,
616
+ :cursor_id => BSON::Int64.new(cursor_id),
614
617
  :db_name => database.name,
615
618
  :coll_name => collection.name
616
619
  }).execute(server)