mongo 2.5.0.beta → 2.5.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 (172) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo/address.rb +1 -1
  5. data/lib/mongo/address/unix.rb +1 -1
  6. data/lib/mongo/auth/user.rb +0 -5
  7. data/lib/mongo/auth/user/view.rb +4 -4
  8. data/lib/mongo/bulk_write.rb +60 -32
  9. data/lib/mongo/client.rb +44 -8
  10. data/lib/mongo/cluster.rb +14 -12
  11. data/lib/mongo/cluster/periodic_executor.rb +106 -0
  12. data/lib/mongo/cluster/{cursor_reaper.rb → reapers/cursor_reaper.rb} +5 -37
  13. data/lib/mongo/cluster/reapers/socket_reaper.rb +59 -0
  14. data/lib/mongo/collection.rb +9 -6
  15. data/lib/mongo/collection/view.rb +2 -2
  16. data/lib/mongo/collection/view/builder/aggregation.rb +2 -1
  17. data/lib/mongo/collection/view/builder/find_command.rb +1 -1
  18. data/lib/mongo/collection/view/change_stream.rb +14 -1
  19. data/lib/mongo/collection/view/map_reduce.rb +30 -13
  20. data/lib/mongo/collection/view/readable.rb +5 -5
  21. data/lib/mongo/collection/view/writable.rb +98 -51
  22. data/lib/mongo/error.rb +3 -0
  23. data/lib/mongo/error/invalid_txt_record.rb +27 -0
  24. data/lib/mongo/error/invalid_uri.rb +7 -6
  25. data/lib/mongo/error/mismatched_domain.rb +27 -0
  26. data/lib/mongo/error/no_srv_records.rb +26 -0
  27. data/lib/mongo/error/unsupported_features.rb +0 -18
  28. data/lib/mongo/index/view.rb +2 -2
  29. data/lib/mongo/operation.rb +1 -0
  30. data/lib/mongo/operation/causally_consistent.rb +33 -0
  31. data/lib/mongo/operation/commands.rb +2 -1
  32. data/lib/mongo/operation/commands/aggregate.rb +2 -7
  33. data/lib/mongo/operation/commands/count.rb +27 -0
  34. data/lib/mongo/operation/commands/distinct.rb +27 -0
  35. data/lib/mongo/operation/commands/find.rb +3 -1
  36. data/lib/mongo/operation/commands/map_reduce.rb +1 -0
  37. data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
  38. data/lib/mongo/operation/specifiable.rb +12 -0
  39. data/lib/mongo/operation/uses_command_op_msg.rb +36 -5
  40. data/lib/mongo/operation/write.rb +0 -5
  41. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -8
  42. data/lib/mongo/operation/write/bulk/mergable.rb +2 -0
  43. data/lib/mongo/operation/write/command/create_index.rb +19 -0
  44. data/lib/mongo/operation/write/command/create_user.rb +19 -0
  45. data/lib/mongo/operation/write/command/delete.rb +1 -2
  46. data/lib/mongo/operation/write/command/drop_index.rb +19 -0
  47. data/lib/mongo/operation/write/command/insert.rb +1 -2
  48. data/lib/mongo/operation/write/command/remove_user.rb +19 -0
  49. data/lib/mongo/operation/write/command/update.rb +1 -2
  50. data/lib/mongo/operation/write/command/update_user.rb +19 -0
  51. data/lib/mongo/operation/write/write_command_enabled.rb +1 -3
  52. data/lib/mongo/protocol/compressed.rb +2 -1
  53. data/lib/mongo/protocol/serializers.rb +6 -6
  54. data/lib/mongo/retryable.rb +48 -5
  55. data/lib/mongo/server.rb +15 -0
  56. data/lib/mongo/server/connection.rb +21 -1
  57. data/lib/mongo/server/connection_pool.rb +3 -0
  58. data/lib/mongo/server/connection_pool/queue.rb +50 -5
  59. data/lib/mongo/server/description.rb +11 -3
  60. data/lib/mongo/server/description/features.rb +26 -7
  61. data/lib/mongo/session.rb +133 -6
  62. data/lib/mongo/session/server_session.rb +30 -0
  63. data/lib/mongo/session/session_pool.rb +20 -20
  64. data/lib/mongo/uri.rb +88 -44
  65. data/lib/mongo/uri/srv_protocol.rb +158 -0
  66. data/lib/mongo/version.rb +1 -1
  67. data/lib/mongo/write_concern/normalizable.rb +12 -0
  68. data/mongo.gemspec +1 -2
  69. data/spec/mongo/address_spec.rb +12 -0
  70. data/spec/mongo/auth/user/view_spec.rb +1 -5
  71. data/spec/mongo/bulk_write_spec.rb +232 -401
  72. data/spec/mongo/change_stream_examples_spec.rb +150 -0
  73. data/spec/mongo/client_spec.rb +142 -2
  74. data/spec/mongo/cluster/cursor_reaper_spec.rb +0 -70
  75. data/spec/mongo/cluster/socket_reaper_spec.rb +32 -0
  76. data/spec/mongo/cluster_spec.rb +11 -7
  77. data/spec/mongo/collection/view/aggregation_spec.rb +46 -1
  78. data/spec/mongo/collection/view/builder/find_command_spec.rb +15 -0
  79. data/spec/mongo/collection/view/change_stream_spec.rb +79 -12
  80. data/spec/mongo/collection/view/map_reduce_spec.rb +120 -4
  81. data/spec/mongo/collection/view/readable_spec.rb +23 -5
  82. data/spec/mongo/collection_spec.rb +292 -102
  83. data/spec/mongo/command_monitoring_spec.rb +26 -32
  84. data/spec/mongo/crud_spec.rb +1 -1
  85. data/spec/mongo/cursor_spec.rb +2 -3
  86. data/spec/mongo/database_spec.rb +30 -14
  87. data/spec/mongo/dns_seedlist_discovery_spec.rb +94 -0
  88. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  89. data/spec/mongo/grid/stream/write_spec.rb +1 -1
  90. data/spec/mongo/index/view_spec.rb +8 -46
  91. data/spec/mongo/operation/write/bulk/delete_spec.rb +2 -2
  92. data/spec/mongo/operation/write/bulk/insert_spec.rb +2 -10
  93. data/spec/mongo/operation/write/{create_index_spec.rb → command/create_index_spec.rb} +2 -6
  94. data/spec/mongo/operation/write/command/delete_spec.rb +35 -7
  95. data/spec/mongo/operation/write/{drop_index_spec.rb → command/drop_index_spec.rb} +1 -1
  96. data/spec/mongo/operation/write/command/insert_spec.rb +37 -6
  97. data/spec/mongo/operation/write/{remove_user_spec.rb → command/remove_user_spec.rb} +2 -6
  98. data/spec/mongo/operation/write/command/update_spec.rb +34 -7
  99. data/spec/mongo/operation/write/{update_user_spec.rb → command/update_user_spec.rb} +1 -1
  100. data/spec/mongo/operation/write/create_user_spec.rb +1 -1
  101. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  102. data/spec/mongo/operation/write/insert_spec.rb +2 -10
  103. data/spec/mongo/operation/write/update_spec.rb +3 -15
  104. data/spec/mongo/retryable_spec.rb +1 -1
  105. data/spec/mongo/retryable_writes_spec.rb +815 -0
  106. data/spec/mongo/server/connection_pool/queue_spec.rb +35 -2
  107. data/spec/mongo/server/connection_pool_spec.rb +234 -1
  108. data/spec/mongo/server/connection_spec.rb +10 -6
  109. data/spec/mongo/server/description/features_spec.rb +51 -37
  110. data/spec/mongo/server/description_spec.rb +6 -3
  111. data/spec/mongo/server_spec.rb +87 -0
  112. data/spec/mongo/session/server_session_spec.rb +43 -0
  113. data/spec/mongo/session/session_pool_spec.rb +63 -27
  114. data/spec/mongo/session_spec.rb +247 -0
  115. data/spec/mongo/shell_examples_spec.rb +2 -2
  116. data/spec/mongo/uri/srv_protocol_spec.rb +933 -0
  117. data/spec/mongo/uri_spec.rb +42 -3
  118. data/spec/mongo/write_concern/acknowledged_spec.rb +11 -0
  119. data/spec/mongo/write_concern/unacknowledged_spec.rb +11 -0
  120. data/spec/spec_helper.rb +11 -25
  121. data/spec/support/authorization.rb +2 -1
  122. data/spec/support/connection_string.rb +8 -4
  123. data/spec/support/crud.rb +38 -24
  124. data/spec/support/crud/write.rb +30 -3
  125. data/spec/support/crud_tests/read/aggregate-out.yml +21 -0
  126. data/spec/support/crud_tests/write/bulkWrite-arrayFilters.yml +44 -0
  127. data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +1 -1
  128. data/spec/support/crud_tests/write/insertMany.yml +1 -3
  129. data/spec/support/crud_tests/write/replaceOne.yml +1 -1
  130. data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +1 -1
  131. data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +1 -1
  132. data/spec/support/dns_seedlist_discovery_tests/longer-parent-in-return.yml +11 -0
  133. data/spec/support/dns_seedlist_discovery_tests/misformatted-option.yml +5 -0
  134. data/spec/support/dns_seedlist_discovery_tests/no-results.yml +5 -0
  135. data/spec/support/dns_seedlist_discovery_tests/not-enough-parts.yml +5 -0
  136. data/spec/support/dns_seedlist_discovery_tests/one-result-default-port.yml +10 -0
  137. data/spec/support/dns_seedlist_discovery_tests/one-txt-record-multiple-strings.yml +10 -0
  138. data/spec/support/dns_seedlist_discovery_tests/one-txt-record.yml +11 -0
  139. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch1.yml +5 -0
  140. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch2.yml +5 -0
  141. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch3.yml +5 -0
  142. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch4.yml +5 -0
  143. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch5.yml +5 -0
  144. data/spec/support/dns_seedlist_discovery_tests/returned-parent-too-short.yml +5 -0
  145. data/spec/support/dns_seedlist_discovery_tests/returned-parent-wrong.yml +5 -0
  146. data/spec/support/dns_seedlist_discovery_tests/two-results-default-port.yml +11 -0
  147. data/spec/support/dns_seedlist_discovery_tests/two-results-nonstandard-port.yml +11 -0
  148. data/spec/support/dns_seedlist_discovery_tests/two-txt-records.yml +5 -0
  149. data/spec/support/dns_seedlist_discovery_tests/txt-record-not-allowed-option.yml +5 -0
  150. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-ssl-option.yml +11 -0
  151. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-uri-option.yml +11 -0
  152. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-unallowed-option.yml +5 -0
  153. data/spec/support/dns_seedlist_discovery_tests/uri-with-port.yml +5 -0
  154. data/spec/support/dns_seedlist_discovery_tests/uri-with-two-hosts.yml +5 -0
  155. data/spec/support/retryable_writes_tests/bulkWrite.yml +305 -0
  156. data/spec/support/retryable_writes_tests/deleteOne.yml +51 -0
  157. data/spec/support/retryable_writes_tests/findOneAndDelete.yml +52 -0
  158. data/spec/support/retryable_writes_tests/findOneAndReplace.yml +57 -0
  159. data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +56 -0
  160. data/spec/support/retryable_writes_tests/insertMany.yml +72 -0
  161. data/spec/support/retryable_writes_tests/insertOne.yml +55 -0
  162. data/spec/support/retryable_writes_tests/replaceOne.yml +60 -0
  163. data/spec/support/retryable_writes_tests/updateOne.yml +120 -0
  164. data/spec/support/shared/session.rb +525 -24
  165. metadata +437 -350
  166. metadata.gz.sig +0 -0
  167. data/lib/mongo/operation/commands/user_query.rb +0 -72
  168. data/lib/mongo/operation/write/create_index.rb +0 -67
  169. data/lib/mongo/operation/write/create_user.rb +0 -50
  170. data/lib/mongo/operation/write/drop_index.rb +0 -63
  171. data/lib/mongo/operation/write/remove_user.rb +0 -48
  172. data/lib/mongo/operation/write/update_user.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4e52038faa9ef6ff0419d1c5855800d4ce07066
4
- data.tar.gz: a7b342d735714530107b7b513ee91c8d071472ba
3
+ metadata.gz: 4a0c8476badc0a3215c3e04955d182d0f5d8eff0
4
+ data.tar.gz: 8e22da76ade8734b4a58a9fbac4aa0524825800e
5
5
  SHA512:
6
- metadata.gz: eb58160cfaa1676ee31df0fcd375e2cad12953b46ba063b8a5f46c6e9dcbdcbf750a5c299e8b4222b3af57c9a0902c9f64fe4dfc33dc37df689730cf19f88e27
7
- data.tar.gz: 97cc226f8bc3fc8fd7bda2d1be3b29be4a8d03f1e444b572dc74008e1276f733a3408851132cef3241df936c4e1613e4bce2ef2b3597e2fb55031ccfed49fb4c
6
+ metadata.gz: cc6f598c936f2aff4eea3fa9d9eb00eea905912c1d2c587d6b307f3d97655d29bd5fd12dd02a6548a384fe04e82b169ff22c5d9ed7db77ec74e7073793345d27
7
+ data.tar.gz: 118a7e1f0942d35672138d6a3ab0d1b3967122d14344fe7cc3645d1a3b511dfd7cf6b05ad547e2b04ee19230dd30f8978f004bddec7952c230183948e8180ceb
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/lib/mongo/address.rb CHANGED
@@ -185,7 +185,7 @@ module Mongo
185
185
  error = nil
186
186
  ::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM).each do |info|
187
187
  begin
188
- res = FAMILY_MAP[info[4]].new(info[3], port, host)
188
+ res = FAMILY_MAP[info[4]].new(host, port, host)
189
189
  res.socket(connect_timeout, ssl_options).connect!(connect_timeout).close
190
190
  return res
191
191
  rescue IOError, SystemCallError, Error::SocketTimeoutError, Error::SocketError => e
@@ -62,7 +62,7 @@ module Mongo
62
62
  # @example Get a Unix socket.
63
63
  # address.socket(5)
64
64
  #
65
- # @param [ Float ] timeout The socket timeout.
65
+ # @param [ Float ] socket_timeout The socket timeout.
66
66
  # @param [ Hash ] ssl_options SSL options - ignored.
67
67
  #
68
68
  # @return [ Pool::Socket::Unix ] The socket.
@@ -22,11 +22,6 @@ module Mongo
22
22
  # @since 2.0.0
23
23
  class User
24
24
 
25
- # The users collection for the database.
26
- #
27
- # @since 2.0.0
28
- COLLECTION = 'system.users'.freeze
29
-
30
25
  # @return [ String ] The authorization source, either a database or
31
26
  # external name.
32
27
  attr_reader :auth_source
@@ -44,7 +44,7 @@ module Mongo
44
44
  def create(user_or_name, options = {})
45
45
  user = generate(user_or_name, options)
46
46
  client.send(:with_session, options) do |session|
47
- Operation::Write::CreateUser.new(
47
+ Operation::Write::Command::CreateUser.new(
48
48
  user: user,
49
49
  db_name: database.name,
50
50
  session: session
@@ -79,7 +79,7 @@ module Mongo
79
79
  # @since 2.0.0
80
80
  def remove(name, options = {})
81
81
  client.send(:with_session, options) do |session|
82
- Operation::Write::RemoveUser.new(
82
+ Operation::Write::Command::RemoveUser.new(
83
83
  user_name: name,
84
84
  db_name: database.name,
85
85
  session: session
@@ -103,7 +103,7 @@ module Mongo
103
103
  def update(user_or_name, options = {})
104
104
  client.send(:with_session, options) do |session|
105
105
  user = generate(user_or_name, options)
106
- Operation::Write::UpdateUser.new(
106
+ Operation::Write::Command::UpdateUser.new(
107
107
  user: user,
108
108
  db_name: database.name,
109
109
  session: session
@@ -132,7 +132,7 @@ module Mongo
132
132
 
133
133
  def user_query(name, options = {})
134
134
  client.send(:with_session, options) do |session|
135
- Operation::Commands::UserQuery.new(
135
+ Operation::Commands::UsersInfo.new(
136
136
  user_name: name,
137
137
  db_name: database.name,
138
138
  session: session
@@ -53,22 +53,31 @@ module Mongo
53
53
  def execute
54
54
  operation_id = Monitoring.next_operation_id
55
55
  result_combiner = ResultCombiner.new
56
+ operations = op_combiner.combine
56
57
 
57
58
  client.send(:with_session, @options) do |session|
58
- write_with_retry(session, Proc.new { next_primary }) do |server|
59
- operations = op_combiner.combine
60
- raise Error::UnsupportedCollation.new if op_combiner.has_collation && !server.features.collation_enabled?
61
- raise Error::UnsupportedArrayFilters.new if op_combiner.has_array_filters && !server.features.array_filters_enabled?
62
-
63
- operations.each do |operation|
64
- execute_operation(
65
- operation.keys.first,
66
- operation.values.first,
67
- server,
68
- operation_id,
69
- result_combiner,
70
- session
71
- )
59
+ operations.each do |operation|
60
+ if single_statement?(operation)
61
+ write_with_retry(session, write_concern) do |server, txn_num|
62
+ execute_operation(
63
+ operation.keys.first,
64
+ operation.values.first,
65
+ server,
66
+ operation_id,
67
+ result_combiner,
68
+ session,
69
+ txn_num)
70
+ end
71
+ else
72
+ legacy_write_with_retry do |server|
73
+ execute_operation(
74
+ operation.keys.first,
75
+ operation.values.first,
76
+ server,
77
+ operation_id,
78
+ result_combiner,
79
+ session)
80
+ end
72
81
  end
73
82
  end
74
83
  end
@@ -137,6 +146,14 @@ module Mongo
137
146
 
138
147
  private
139
148
 
149
+ SINGLE_STATEMENT_OPS = [ :delete_one,
150
+ :update_one,
151
+ :insert_one ].freeze
152
+
153
+ def single_statement?(operation)
154
+ SINGLE_STATEMENT_OPS.include?(operation.keys.first)
155
+ end
156
+
140
157
  def base_spec(operation_id, session)
141
158
  {
142
159
  :db_name => database.name,
@@ -151,16 +168,18 @@ module Mongo
151
168
  }
152
169
  end
153
170
 
154
- def execute_operation(name, values, server, operation_id, combiner, session)
171
+ def execute_operation(name, values, server, operation_id, combiner, session, txn_num = nil)
172
+ raise Error::UnsupportedCollation.new if op_combiner.has_collation && !server.features.collation_enabled?
173
+ raise Error::UnsupportedArrayFilters.new if op_combiner.has_array_filters && !server.features.array_filters_enabled?
155
174
  begin
156
175
  if values.size > server.max_write_batch_size
157
- split_execute(name, values, server, operation_id, combiner, session)
176
+ split_execute(name, values, server, operation_id, combiner, session, txn_num)
158
177
  else
159
- combiner.combine!(send(name, values, server, operation_id, session), values.size)
178
+ combiner.combine!(send(name, values, server, operation_id, session, txn_num), values.size)
160
179
  end
161
180
  rescue Error::MaxBSONSize, Error::MaxMessageSize => e
162
181
  raise e if values.size <= 1
163
- split_execute(name, values, server, operation_id, combiner, session)
182
+ split_execute(name, values, server, operation_id, combiner, session, txn_num)
164
183
  end
165
184
  end
166
185
 
@@ -168,34 +187,43 @@ module Mongo
168
187
  @op_combiner ||= ordered? ? OrderedCombiner.new(requests) : UnorderedCombiner.new(requests)
169
188
  end
170
189
 
171
- def split_execute(name, values, server, operation_id, combiner, session)
172
- execute_operation(name, values.shift(values.size / 2), server, operation_id, combiner, session)
173
- execute_operation(name, values, server, operation_id, combiner, session)
190
+ def split_execute(name, values, server, operation_id, combiner, session, txn_num)
191
+ execute_operation(name, values.shift(values.size / 2), server, operation_id, combiner, session, txn_num)
192
+
193
+ txn_num = session.next_txn_num if txn_num
194
+ execute_operation(name, values, server, operation_id, combiner, session, txn_num)
174
195
  end
175
196
 
176
- def delete(documents, server, operation_id, session)
197
+ def delete_one(documents, server, operation_id, session, txn_num)
177
198
  Operation::Write::Bulk::Delete.new(
178
- base_spec(operation_id, session).merge(:deletes => documents)
199
+ base_spec(operation_id, session).merge(:deletes => documents, :txn_num => txn_num)
200
+ ).execute(server)
201
+ end
202
+
203
+ def delete_many(documents, server, operation_id, session, txn_num)
204
+ Operation::Write::Bulk::Delete.new(
205
+ base_spec(operation_id, session).merge(:deletes => documents)
179
206
  ).execute(server)
180
207
  end
181
208
 
182
- alias :delete_one :delete
183
- alias :delete_many :delete
184
209
 
185
- def insert_one(documents, server, operation_id, session)
210
+ def insert_one(documents, server, operation_id, session, txn_num)
186
211
  Operation::Write::Bulk::Insert.new(
187
- base_spec(operation_id, session).merge(:documents => documents)
212
+ base_spec(operation_id, session).merge(:documents => documents, :txn_num => txn_num)
188
213
  ).execute(server)
189
214
  end
190
215
 
191
- def update(documents, server, operation_id, session)
216
+ def update_one(documents, server, operation_id, session, txn_num)
192
217
  Operation::Write::Bulk::Update.new(
193
- base_spec(operation_id, session).merge(:updates => documents)
218
+ base_spec(operation_id, session).merge(:updates => documents, :txn_num => txn_num)
194
219
  ).execute(server)
195
220
  end
221
+ alias :replace_one :update_one
196
222
 
197
- alias :replace_one :update
198
- alias :update_one :update
199
- alias :update_many :update
223
+ def update_many(documents, server, operation_id, session, txn_num)
224
+ Operation::Write::Bulk::Update.new(
225
+ base_spec(operation_id, session).merge(:updates => documents)
226
+ ).execute(server)
227
+ end
200
228
  end
201
229
  end
data/lib/mongo/client.rb CHANGED
@@ -44,6 +44,7 @@ module Mongo
44
44
  :id_generator,
45
45
  :local_threshold,
46
46
  :logger,
47
+ :max_idle_time,
47
48
  :max_pool_size,
48
49
  :max_read_retries,
49
50
  :min_pool_size,
@@ -53,6 +54,7 @@ module Mongo
53
54
  :read,
54
55
  :read_retry_interval,
55
56
  :replica_set,
57
+ :retry_writes,
56
58
  :server_selection_timeout,
57
59
  :socket_timeout,
58
60
  :ssl,
@@ -166,6 +168,8 @@ module Mongo
166
168
  # @option options [ Integer ] :server_selection_timeout The timeout in seconds
167
169
  # for selecting a server for an operation.
168
170
  # @option options [ String ] :password The user's password.
171
+ # @option options [ Integer ] :max_idle_time The maximum seconds a socket can remain idle
172
+ # since it has been checked in to the pool.
169
173
  # @option options [ Integer ] :max_pool_size The maximum size of the
170
174
  # connection pool.
171
175
  # @option options [ Integer ] :min_pool_size The minimum size of the
@@ -174,8 +178,9 @@ module Mongo
174
178
  # seconds, in the connection pool for a connection to be checked in.
175
179
  # @option options [ Float ] :connect_timeout The timeout, in seconds, to
176
180
  # attempt a connection.
177
- # @option options [ Array<String> ] :compressors The compressor to use. Currently the driver
178
- # only supports zlib.
181
+ # @option options [ Array<String> ] :compressors A list of potential compressors to use, in order of preference.
182
+ # The driver chooses the first compressor that is also supported by the server. Currently the driver only
183
+ # supports 'zlib'.
179
184
  # @option options [ Hash ] :read The read preference options. They consist of a
180
185
  # mode specified as a symbol, an array of hashes known as tag_sets,
181
186
  # and local_threshold.
@@ -236,6 +241,10 @@ module Mongo
236
241
  # mongod logs upon establishing a connection in server versions >= 3.4.
237
242
  # @option options [ String ] :platform Platform information to include in the
238
243
  # metadata printed to the mongod logs upon establishing a connection in server versions >= 3.4.
244
+ # @option options [ Integer ] :zlib_compression_level The Zlib compression level to use, if using compression.
245
+ # See Ruby's Zlib module for valid levels.
246
+ # @option options [ true, false ] :retry_writes Retry writes once when connected to a replica set
247
+ # or sharded cluster versions 3.6 and up.
239
248
  #
240
249
  # @since 2.0.0
241
250
  def initialize(addresses_or_uri, options = Options::Redacted.new)
@@ -387,11 +396,14 @@ module Mongo
387
396
  # @example Get the database names.
388
397
  # client.database_names
389
398
  #
399
+ # @param [ Hash ] filter The filter criteria for getting a list of databases.
400
+ # @param [ Hash ] opts The command options.
401
+ #
390
402
  # @return [ Array<String> ] The names of the databases.
391
403
  #
392
404
  # @since 2.0.5
393
- def database_names
394
- list_databases.collect{ |info| info[Database::NAME] }
405
+ def database_names(filter = {}, opts = {})
406
+ list_databases(filter, true, opts).collect{ |info| info[Database::NAME] }
395
407
  end
396
408
 
397
409
  # Get info for each database.
@@ -399,11 +411,35 @@ module Mongo
399
411
  # @example Get the info for each database.
400
412
  # client.list_databases
401
413
  #
414
+ # @param [ Hash ] filter The filter criteria for getting a list of databases.
415
+ # @param [ true, false ] name_only Whether to only return each database name without full metadata.
416
+ # @param [ Hash ] opts The command options.
417
+ #
402
418
  # @return [ Array<Hash> ] The info for each database.
403
419
  #
404
420
  # @since 2.0.5
405
- def list_databases
406
- use(Database::ADMIN).command(listDatabases: 1).first[Database::DATABASES]
421
+ def list_databases(filter = {}, name_only = false, opts = {})
422
+ cmd = { listDatabases: 1 }
423
+ cmd[:nameOnly] = !!name_only
424
+ cmd[:filter] = filter unless filter.empty?
425
+ use(Database::ADMIN).command(cmd, opts).first[Database::DATABASES]
426
+ end
427
+
428
+ # Returns a list of Mongo::Database objects.
429
+ #
430
+ # @example Get a list of Mongo::Database objects.
431
+ # client.list_mongo_databases
432
+ #
433
+ # @param [ Hash ] filter The filter criteria for getting a list of databases.
434
+ # @param [ Hash ] opts The command options.
435
+ #
436
+ # @return [ Array<Mongo::Database> ] The list of database objects.
437
+ #
438
+ # @since 2.5.0
439
+ def list_mongo_databases(filter = {}, opts = {})
440
+ database_names(filter, opts).collect do |name|
441
+ Database.new(self, name, options)
442
+ end
407
443
  end
408
444
 
409
445
  # Start a session.
@@ -451,7 +487,7 @@ module Mongo
451
487
  end
452
488
 
453
489
  def sessions_supported?
454
- if cluster.servers.empty?
490
+ if cluster.servers.empty? && !cluster.topology.single?
455
491
  ServerSelector.get(mode: :primary_preferred).select_server(cluster)
456
492
  end
457
493
  !!logical_session_timeout
@@ -465,7 +501,7 @@ module Mongo
465
501
  end
466
502
 
467
503
  def create_from_uri(connection_string, opts = Options::Redacted.new)
468
- uri = URI.new(connection_string, opts)
504
+ uri = URI.get(connection_string, opts)
469
505
  @options = validate_options!(Database::DEFAULT_OPTIONS.merge(uri.client_options.merge(opts))).freeze
470
506
  @cluster = Cluster.new(uri.servers, @monitoring, options)
471
507
  @database = Database.new(self, options[:database], options)
data/lib/mongo/cluster.rb CHANGED
@@ -13,7 +13,9 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'mongo/cluster/topology'
16
- require 'mongo/cluster/cursor_reaper'
16
+ require 'mongo/cluster/reapers/socket_reaper'
17
+ require 'mongo/cluster/reapers/cursor_reaper'
18
+ require 'mongo/cluster/periodic_executor'
17
19
  require 'mongo/cluster/app_metadata'
18
20
 
19
21
  module Mongo
@@ -189,9 +191,11 @@ module Mongo
189
191
  ) if @servers.size > 1
190
192
 
191
193
  @cursor_reaper = CursorReaper.new
192
- @cursor_reaper.run!
194
+ @socket_reaper = SocketReaper.new(self)
195
+ @periodic_executor = PeriodicExecutor.new(@cursor_reaper, @socket_reaper)
196
+ @periodic_executor.run!
193
197
 
194
- ObjectSpace.define_finalizer(self, self.class.finalize(pools, @cursor_reaper))
198
+ ObjectSpace.define_finalizer(self, self.class.finalize(pools, @periodic_executor))
195
199
  end
196
200
 
197
201
  # Finalize the cluster for garbage collection. Disconnects all the scoped
@@ -206,10 +210,9 @@ module Mongo
206
210
  # @return [ Proc ] The Finalizer.
207
211
  #
208
212
  # @since 2.2.0
209
- def self.finalize(pools, cursor_reaper)
213
+ def self.finalize(pools, periodic_executor)
210
214
  proc do
211
- begin; cursor_reaper.kill_cursors; rescue; end
212
- cursor_reaper.stop!
215
+ periodic_executor.stop!
213
216
  pools.values.each do |pool|
214
217
  pool.disconnect!
215
218
  end
@@ -371,8 +374,7 @@ module Mongo
371
374
  #
372
375
  # @since 2.1.0
373
376
  def disconnect!
374
- begin; @cursor_reaper.kill_cursors; rescue; end
375
- @cursor_reaper.stop!
377
+ @periodic_executor.stop!
376
378
  @servers.each { |server| server.disconnect! } and true
377
379
  end
378
380
 
@@ -387,7 +389,7 @@ module Mongo
387
389
  def reconnect!
388
390
  scan!
389
391
  servers.each { |server| server.reconnect! }
390
- @cursor_reaper.restart! and true
392
+ @periodic_executor.restart! and true
391
393
  end
392
394
 
393
395
  # Add hosts in a description to the cluster.
@@ -474,7 +476,7 @@ module Mongo
474
476
  # @example Update the cluster time.
475
477
  # cluster.update_cluster_time(result)
476
478
  #
477
- # @param [ Operation::Result ] The operation result containing the cluster time.
479
+ # @param [ Operation::Result ] result The operation result containing the cluster time.
478
480
  #
479
481
  # @return [ Object ] The cluster time.
480
482
  #
@@ -484,8 +486,8 @@ module Mongo
484
486
  @cluster_time_lock.synchronize do
485
487
  if @cluster_time.nil?
486
488
  @cluster_time = cluster_time_doc
487
- else
488
- @cluster_time = cluster_time_doc if cluster_time_doc[CLUSTER_TIME] > @cluster_time[CLUSTER_TIME]
489
+ elsif cluster_time_doc[CLUSTER_TIME] > @cluster_time[CLUSTER_TIME]
490
+ @cluster_time = cluster_time_doc
489
491
  end
490
492
  end
491
493
  end
@@ -0,0 +1,106 @@
1
+ # Copyright (C) 2014-2017 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
+
17
+ class Cluster
18
+
19
+ # A manager that calls #execute on its executors at a regular interval.
20
+ #
21
+ # @api private
22
+ #
23
+ # @since 2.5.0
24
+ class PeriodicExecutor
25
+
26
+ # The default time interval for the periodic executor to execute.
27
+ #
28
+ # @since 2.5.0
29
+ FREQUENCY = 5
30
+
31
+ # Create a periodic executor.
32
+ #
33
+ # @example Create a PeriodicExecutor.
34
+ # Mongo::Cluster::PeriodicExecutor.new(reaper, reaper2)
35
+ #
36
+ # @api private
37
+ #
38
+ # @since 2.5.0
39
+ def initialize(*executors)
40
+ @thread = nil
41
+ @executors = executors
42
+ end
43
+
44
+ # Start the thread.
45
+ #
46
+ # @example Start the periodic executor's thread.
47
+ # periodic_executor.run!
48
+ #
49
+ # @api private
50
+ #
51
+ # @since 2.5.0
52
+ def run!
53
+ @thread && @thread.alive? ? @thread : start!
54
+ end
55
+ alias :restart! :run!
56
+
57
+ # Stop the executor's thread.
58
+ #
59
+ # @example Stop the executors's thread.
60
+ # periodic_executor.stop!
61
+ #
62
+ # @api private
63
+ #
64
+ # @since 2.5.0
65
+ def stop!
66
+ begin; flush; rescue; end
67
+ @thread.kill && @thread.stop?
68
+ end
69
+
70
+ # Trigger an execute call on each reaper.
71
+ #
72
+ # @example Trigger all reapers.
73
+ # periodic_executor.execute
74
+ #
75
+ # @api private
76
+ #
77
+ # @since 2.5.0
78
+ def execute
79
+ @executors.each(&:execute) and true
80
+ end
81
+
82
+ # Execute all pending operations.
83
+ #
84
+ # @example Execute all pending operations.
85
+ # periodic_executor.flush
86
+ #
87
+ # @api private
88
+ #
89
+ # @since 2.5.0
90
+ def flush
91
+ @executors.each(&:flush) and true
92
+ end
93
+
94
+ private
95
+
96
+ def start!
97
+ @thread = Thread.new(FREQUENCY) do |i|
98
+ loop do
99
+ sleep(i)
100
+ execute
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end