mongo 2.5.0.beta → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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