mongo 2.8.0 → 2.9.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 (276) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +12 -0
  5. data/lib/mongo.rb +15 -1
  6. data/lib/mongo/address/ipv6.rb +0 -2
  7. data/lib/mongo/auth/scram/conversation.rb +0 -3
  8. data/lib/mongo/bulk_write/result_combiner.rb +12 -2
  9. data/lib/mongo/client.rb +59 -6
  10. data/lib/mongo/cluster.rb +19 -8
  11. data/lib/mongo/cluster/reapers/cursor_reaper.rb +0 -2
  12. data/lib/mongo/cluster/reapers/socket_reaper.rb +12 -9
  13. data/lib/mongo/collection.rb +1 -1
  14. data/lib/mongo/collection/view/aggregation.rb +5 -1
  15. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  16. data/lib/mongo/collection/view/change_stream.rb +30 -10
  17. data/lib/mongo/collection/view/iterable.rb +13 -6
  18. data/lib/mongo/collection/view/map_reduce.rb +12 -10
  19. data/lib/mongo/collection/view/readable.rb +19 -14
  20. data/lib/mongo/cursor.rb +12 -8
  21. data/lib/mongo/database.rb +10 -7
  22. data/lib/mongo/database/view.rb +18 -11
  23. data/lib/mongo/error.rb +2 -2
  24. data/lib/mongo/error/connection_check_out_timeout.rb +49 -0
  25. data/lib/mongo/error/operation_failure.rb +9 -9
  26. data/lib/mongo/error/parser.rb +25 -3
  27. data/lib/mongo/error/pool_closed_error.rb +43 -0
  28. data/lib/mongo/error/sdam_error_detection.rb +18 -0
  29. data/lib/mongo/grid/file/chunk.rb +0 -2
  30. data/lib/mongo/grid/fs_bucket.rb +26 -12
  31. data/lib/mongo/grid/stream/read.rb +36 -21
  32. data/lib/mongo/index/view.rb +11 -7
  33. data/lib/mongo/logger.rb +0 -2
  34. data/lib/mongo/monitoring.rb +31 -0
  35. data/lib/mongo/monitoring/cmap_log_subscriber.rb +53 -0
  36. data/lib/mongo/monitoring/event.rb +1 -0
  37. data/lib/mongo/monitoring/event/cmap.rb +25 -0
  38. data/lib/mongo/monitoring/event/cmap/base.rb +28 -0
  39. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +78 -0
  40. data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +56 -0
  41. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +63 -0
  42. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +64 -0
  43. data/lib/mongo/monitoring/event/cmap/connection_closed.rb +103 -0
  44. data/lib/mongo/monitoring/event/cmap/connection_created.rb +64 -0
  45. data/lib/mongo/monitoring/event/cmap/connection_ready.rb +64 -0
  46. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +57 -0
  47. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +57 -0
  48. data/lib/mongo/monitoring/event/cmap/pool_created.rb +63 -0
  49. data/lib/mongo/monitoring/event/command_started.rb +12 -3
  50. data/lib/mongo/monitoring/publishable.rb +10 -2
  51. data/lib/mongo/operation.rb +0 -1
  52. data/lib/mongo/operation/find/legacy/result.rb +1 -0
  53. data/lib/mongo/operation/list_collections/result.rb +7 -1
  54. data/lib/mongo/operation/result.rb +10 -1
  55. data/lib/mongo/operation/shared/executable.rb +15 -0
  56. data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +29 -0
  57. data/lib/mongo/operation/shared/specifiable.rb +0 -16
  58. data/lib/mongo/operation/update/legacy/result.rb +1 -0
  59. data/lib/mongo/protocol/compressed.rb +0 -2
  60. data/lib/mongo/protocol/msg.rb +25 -2
  61. data/lib/mongo/retryable.rb +171 -33
  62. data/lib/mongo/server.rb +26 -7
  63. data/lib/mongo/server/app_metadata.rb +0 -2
  64. data/lib/mongo/server/connectable.rb +8 -2
  65. data/lib/mongo/server/connection.rb +83 -13
  66. data/lib/mongo/server/connection_base.rb +1 -1
  67. data/lib/mongo/server/connection_pool.rb +439 -43
  68. data/lib/mongo/server/monitor/connection.rb +4 -1
  69. data/lib/mongo/session.rb +37 -5
  70. data/lib/mongo/session/session_pool.rb +2 -2
  71. data/lib/mongo/socket.rb +0 -2
  72. data/lib/mongo/socket/ssl.rb +0 -2
  73. data/lib/mongo/uri.rb +127 -66
  74. data/lib/mongo/uri/srv_protocol.rb +35 -13
  75. data/lib/mongo/version.rb +1 -1
  76. data/spec/README.md +190 -63
  77. data/spec/integration/change_stream_spec.rb +64 -0
  78. data/spec/integration/command_spec.rb +0 -7
  79. data/spec/integration/error_detection_spec.rb +39 -0
  80. data/spec/integration/read_concern.rb +83 -0
  81. data/spec/integration/retryable_writes_spec.rb +6 -50
  82. data/spec/integration/sdam_error_handling_spec.rb +60 -7
  83. data/spec/integration/ssl_uri_options_spec.rb +24 -0
  84. data/spec/integration/step_down_spec.rb +197 -0
  85. data/spec/lite_spec_helper.rb +4 -0
  86. data/spec/mongo/client_construction_spec.rb +42 -17
  87. data/spec/mongo/client_spec.rb +32 -1
  88. data/spec/mongo/cluster/socket_reaper_spec.rb +2 -2
  89. data/spec/mongo/cluster_spec.rb +36 -2
  90. data/spec/mongo/collection/view/aggregation_spec.rb +2 -0
  91. data/spec/mongo/collection/view/change_stream_spec.rb +28 -28
  92. data/spec/mongo/collection/view/readable_spec.rb +1 -1
  93. data/spec/mongo/collection/view_spec.rb +3 -1
  94. data/spec/mongo/cursor_spec.rb +5 -5
  95. data/spec/mongo/error/parser_spec.rb +61 -1
  96. data/spec/mongo/grid/stream/read_spec.rb +2 -2
  97. data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +23 -0
  98. data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +19 -0
  99. data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +23 -0
  100. data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +23 -0
  101. data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +27 -0
  102. data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +24 -0
  103. data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +24 -0
  104. data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +19 -0
  105. data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +19 -0
  106. data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +26 -0
  107. data/spec/mongo/operation/delete/bulk_spec.rb +1 -6
  108. data/spec/mongo/operation/delete/command_spec.rb +1 -1
  109. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
  110. data/spec/mongo/operation/delete_spec.rb +4 -4
  111. data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
  112. data/spec/mongo/operation/insert/command_spec.rb +1 -1
  113. data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
  114. data/spec/mongo/operation/update/bulk_spec.rb +1 -1
  115. data/spec/mongo/operation/update/command_spec.rb +2 -2
  116. data/spec/mongo/operation/update/op_msg_spec.rb +2 -2
  117. data/spec/mongo/protocol/msg_spec.rb +11 -0
  118. data/spec/mongo/retryable_spec.rb +78 -25
  119. data/spec/mongo/server/connection_pool_spec.rb +661 -126
  120. data/spec/mongo/server/connection_spec.rb +55 -7
  121. data/spec/mongo/server_spec.rb +5 -0
  122. data/spec/mongo/uri/srv_protocol_spec.rb +135 -2
  123. data/spec/mongo/uri_option_parsing_spec.rb +511 -0
  124. data/spec/mongo/uri_spec.rb +42 -6
  125. data/spec/spec_helper.rb +1 -84
  126. data/spec/spec_tests/cmap_spec.rb +50 -0
  127. data/spec/spec_tests/command_monitoring_spec.rb +7 -18
  128. data/spec/spec_tests/crud_spec.rb +3 -49
  129. data/spec/spec_tests/data/cmap/connection-must-have-id.yml +21 -0
  130. data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +21 -0
  131. data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +24 -0
  132. data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +24 -0
  133. data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +21 -0
  134. data/spec/spec_tests/data/cmap/pool-checkin.yml +18 -0
  135. data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +13 -0
  136. data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +28 -0
  137. data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +34 -0
  138. data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +31 -0
  139. data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +29 -0
  140. data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +26 -0
  141. data/spec/spec_tests/data/cmap/pool-close.yml +11 -0
  142. data/spec/spec_tests/data/cmap/pool-create-max-size.yml +56 -0
  143. data/spec/spec_tests/data/cmap/pool-create-min-size.yml +27 -0
  144. data/spec/spec_tests/data/cmap/pool-create-with-options.yml +20 -0
  145. data/spec/spec_tests/data/cmap/pool-create.yml +12 -0
  146. data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +94 -0
  147. data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +41 -0
  148. data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +157 -0
  149. data/spec/spec_tests/data/retryable_reads/aggregate.yml +87 -0
  150. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +149 -0
  151. data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +61 -0
  152. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +149 -0
  153. data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +65 -0
  154. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +153 -0
  155. data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +61 -0
  156. data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +150 -0
  157. data/spec/spec_tests/data/retryable_reads/count.yml +64 -0
  158. data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +150 -0
  159. data/spec/spec_tests/data/retryable_reads/countDocuments.yml +64 -0
  160. data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +156 -0
  161. data/spec/spec_tests/data/retryable_reads/distinct.yml +71 -0
  162. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +148 -0
  163. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount.yml +62 -0
  164. data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +160 -0
  165. data/spec/spec_tests/data/retryable_reads/find.yml +86 -0
  166. data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +154 -0
  167. data/spec/spec_tests/data/retryable_reads/findOne.yml +68 -0
  168. data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +173 -0
  169. data/spec/spec_tests/data/retryable_reads/gridfs-download.yml +79 -0
  170. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +174 -0
  171. data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName.yml +79 -0
  172. data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +143 -0
  173. data/spec/spec_tests/data/retryable_reads/listCollectionNames.yml +59 -0
  174. data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +144 -0
  175. data/spec/spec_tests/data/retryable_reads/listCollectionObjects.yml +59 -0
  176. data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +143 -0
  177. data/spec/spec_tests/data/retryable_reads/listCollections.yml +59 -0
  178. data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +143 -0
  179. data/spec/spec_tests/data/retryable_reads/listDatabaseNames.yml +59 -0
  180. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +144 -0
  181. data/spec/spec_tests/data/retryable_reads/listDatabaseObjects.yml +59 -0
  182. data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +144 -0
  183. data/spec/spec_tests/data/retryable_reads/listDatabases.yml +59 -0
  184. data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +144 -0
  185. data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +60 -0
  186. data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +145 -0
  187. data/spec/spec_tests/data/retryable_reads/listIndexes.yml +60 -0
  188. data/spec/spec_tests/data/retryable_reads/mapReduce.yml +60 -0
  189. data/spec/spec_tests/data/retryable_writes/bulkWrite-serverErrors.yml +10 -7
  190. data/spec/spec_tests/data/retryable_writes/bulkWrite.yml +15 -22
  191. data/spec/spec_tests/data/retryable_writes/deleteMany.yml +22 -0
  192. data/spec/spec_tests/data/retryable_writes/deleteOne-serverErrors.yml +8 -7
  193. data/spec/spec_tests/data/retryable_writes/deleteOne.yml +5 -8
  194. data/spec/spec_tests/data/retryable_writes/findOneAndDelete-serverErrors.yml +8 -7
  195. data/spec/spec_tests/data/retryable_writes/findOneAndDelete.yml +5 -8
  196. data/spec/spec_tests/data/retryable_writes/findOneAndReplace-serverErrors.yml +8 -7
  197. data/spec/spec_tests/data/retryable_writes/findOneAndReplace.yml +5 -8
  198. data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-serverErrors.yml +8 -7
  199. data/spec/spec_tests/data/retryable_writes/findOneAndUpdate.yml +5 -8
  200. data/spec/spec_tests/data/retryable_writes/insertMany-serverErrors.yml +8 -7
  201. data/spec/spec_tests/data/retryable_writes/insertMany.yml +5 -8
  202. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +10 -45
  203. data/spec/spec_tests/data/retryable_writes/insertOne.yml +5 -8
  204. data/spec/spec_tests/data/retryable_writes/replaceOne-serverErrors.yml +8 -7
  205. data/spec/spec_tests/data/retryable_writes/replaceOne.yml +5 -8
  206. data/spec/spec_tests/data/retryable_writes/updateMany.yml +27 -0
  207. data/spec/spec_tests/data/retryable_writes/updateOne-serverErrors.yml +8 -7
  208. data/spec/spec_tests/data/retryable_writes/updateOne.yml +5 -14
  209. data/spec/spec_tests/data/transactions/abort.yml +7 -2
  210. data/spec/spec_tests/data/transactions/bulk.yml +7 -2
  211. data/spec/spec_tests/data/transactions/causal-consistency.yml +11 -4
  212. data/spec/spec_tests/data/transactions/commit.yml +11 -4
  213. data/spec/spec_tests/data/transactions/count.yml +64 -0
  214. data/spec/spec_tests/data/transactions/delete.yml +7 -2
  215. data/spec/spec_tests/data/transactions/error-labels.yml +8 -2
  216. data/spec/spec_tests/data/transactions/errors.yml +7 -2
  217. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +7 -2
  218. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +7 -2
  219. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +7 -2
  220. data/spec/spec_tests/data/transactions/insert.yml +9 -2
  221. data/spec/spec_tests/data/transactions/isolation.yml +7 -2
  222. data/spec/spec_tests/data/transactions/read-concern.yml +15 -6
  223. data/spec/spec_tests/data/transactions/read-pref.yml +7 -2
  224. data/spec/spec_tests/data/transactions/reads.yml +8 -48
  225. data/spec/spec_tests/data/transactions/retryable-abort.yml +7 -2
  226. data/spec/spec_tests/data/transactions/retryable-commit.yml +7 -2
  227. data/spec/spec_tests/data/transactions/retryable-writes.yml +7 -2
  228. data/spec/spec_tests/data/transactions/run-command.yml +7 -2
  229. data/spec/spec_tests/data/transactions/transaction-options.yml +7 -2
  230. data/spec/spec_tests/data/transactions/update.yml +7 -2
  231. data/spec/spec_tests/data/transactions/write-concern.yml +7 -2
  232. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -1
  233. data/spec/spec_tests/data/transactions_api/callback-commits.yml +6 -1
  234. data/spec/spec_tests/data/transactions_api/callback-retry.yml +6 -1
  235. data/spec/spec_tests/data/transactions_api/commit-retry.yml +6 -1
  236. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +6 -3
  237. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +6 -1
  238. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +6 -1
  239. data/spec/spec_tests/data/transactions_api/commit.yml +6 -1
  240. data/spec/spec_tests/data/transactions_api/transaction-options.yml +6 -1
  241. data/spec/spec_tests/retryable_reads_spec.rb +11 -0
  242. data/spec/spec_tests/retryable_writes_spec.rb +4 -69
  243. data/spec/spec_tests/transactions_api_spec.rb +42 -37
  244. data/spec/spec_tests/transactions_spec.rb +42 -33
  245. data/spec/support/authorization.rb +12 -0
  246. data/spec/support/change_streams/operation.rb +1 -1
  247. data/spec/support/client_registry.rb +20 -0
  248. data/spec/support/cluster_config.rb +16 -15
  249. data/spec/support/cluster_tools.rb +346 -0
  250. data/spec/support/cmap.rb +367 -0
  251. data/spec/support/cmap/verifier.rb +46 -0
  252. data/spec/support/command_monitoring.rb +4 -6
  253. data/spec/support/common_shortcuts.rb +6 -0
  254. data/spec/support/connection_string.rb +2 -2
  255. data/spec/support/crud.rb +171 -184
  256. data/spec/support/crud/operation.rb +43 -0
  257. data/spec/support/crud/outcome.rb +53 -0
  258. data/spec/support/crud/read.rb +102 -12
  259. data/spec/support/crud/requirement.rb +69 -0
  260. data/spec/support/crud/spec.rb +68 -0
  261. data/spec/support/crud/test.rb +141 -0
  262. data/spec/support/crud/verifier.rb +96 -18
  263. data/spec/support/crud/write.rb +18 -3
  264. data/spec/support/event_subscriber.rb +15 -0
  265. data/spec/support/primary_socket.rb +2 -2
  266. data/spec/support/spec_config.rb +89 -20
  267. data/spec/support/transactions.rb +2 -306
  268. data/spec/support/transactions/operation.rb +7 -7
  269. data/spec/support/transactions/spec.rb +28 -0
  270. data/spec/support/transactions/test.rb +191 -0
  271. data/spec/support/utils.rb +123 -0
  272. metadata +202 -9
  273. metadata.gz.sig +0 -0
  274. data/lib/mongo/server/connection_pool/queue.rb +0 -359
  275. data/spec/mongo/server/connection_pool/queue_spec.rb +0 -353
  276. data/spec/support/transactions/verifier.rb +0 -97
metadata.gz.sig CHANGED
Binary file
@@ -1,359 +0,0 @@
1
- # Copyright (C) 2014-2019 MongoDB, Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- module Mongo
16
- class Server
17
- class ConnectionPool
18
-
19
- # A LIFO queue of connections to be used by the connection pool. This is
20
- # based on mperham's connection pool.
21
- #
22
- # @note The queue contains active connections that are available for
23
- # use. It does not track connections which are in use (checked out).
24
- # It is easy to confuse the size of the connection pool (number of
25
- # connections that are used plus number of connections that are
26
- # available for use) and the size of the queue (number of connections
27
- # that have already been created that are available for use).
28
- # API documentation for this class states whether each size refers
29
- # to the pool or to the queue size. Note that minimum and maximum
30
- # sizes only make sense when talking about the connection pool,
31
- # as the size of the queue of available connections is determined by
32
- # the size constraints of the pool plus how many connections are
33
- # currently checked out.
34
- #
35
- # @since 2.0.0
36
- class Queue
37
- include Loggable
38
- extend Forwardable
39
-
40
- # The default max size for the connection pool.
41
- MAX_SIZE = 5.freeze
42
-
43
- # The default min size for the connection pool.
44
- MIN_SIZE = 1.freeze
45
-
46
- # The default timeout, in seconds, to wait for a connection.
47
- WAIT_TIMEOUT = 1.freeze
48
-
49
- # Initialize the new queue. Will yield the block the number of times
50
- # equal to the initial connection pool size.
51
- #
52
- # @example Create the queue.
53
- # Mongo::Server::ConnectionPool::Queue.new(max_pool_size: 5) { Connection.new }
54
- #
55
- # @param [ Hash ] options The options.
56
- #
57
- # @option options [ Integer ] :max_pool_size The maximum pool size.
58
- # @option options [ Integer ] :min_pool_size The minimum pool size.
59
- # @option options [ Float ] :wait_queue_timeout The time to wait, in
60
- # seconds, for a free connection.
61
- #
62
- # @since 2.0.0
63
- def initialize(options = {}, &block)
64
- if options[:min_pool_size] && options[:max_pool_size] &&
65
- options[:min_pool_size] > options[:max_pool_size]
66
- then
67
- raise ArgumentError, "Cannot have min size > max size"
68
- end
69
- @block = block
70
- # This is the number of connections in the pool.
71
- # Includes available connections in the queue and the checked
72
- # out connections that we don't otherwise track.
73
- @pool_size = 0
74
- @options = options
75
- @generation = 1
76
- if min_size > max_size
77
- raise ArgumentError, "min_size (#{min_size}) cannot exceed max_size (#{max_size})"
78
- end
79
- @queue = Array.new(min_size) { create_connection }
80
- @mutex = Mutex.new
81
- @resource = ConditionVariable.new
82
- check_count_invariants
83
- end
84
-
85
- # @return [ Integer ] generation Generation of connections currently
86
- # being used by the queue.
87
- #
88
- # @since 2.7.0
89
- # @api private
90
- attr_reader :generation
91
-
92
- # @return [ Array ] queue The underlying array of connections.
93
- attr_reader :queue
94
-
95
- # @return [ Mutex ] mutex The mutex used for synchronization of
96
- # access to #queue.
97
- #
98
- # @api private
99
- attr_reader :mutex
100
-
101
- # @return [ Hash ] options The options.
102
- attr_reader :options
103
-
104
- # @return [ ConditionVariable ] resource The resource.
105
- attr_reader :resource
106
-
107
- # Number of connections that the pool has which are ready to be
108
- # checked out. This is NOT the size of the connection pool (total
109
- # number of active connections created by the pool).
110
- def size
111
- mutex.synchronize do
112
- queue.size
113
- end
114
- end
115
-
116
- # Number of connections that the pool has which are ready to be
117
- # checked out.
118
- #
119
- # @since 2.7.0
120
- alias_method :queue_size, :size
121
-
122
- # Number of connections in the pool (active connections ready to
123
- # be checked out plus connections already checked out).
124
- #
125
- # @since 2.7.0
126
- attr_reader :pool_size
127
-
128
- # Retrieves a connection. If there are active connections in the
129
- # queue, the most recently used connection is returned. Otherwise
130
- # if the connection pool size is less than the max size, creates a
131
- # new connection and returns it. Otherwise raises Timeout::Error.
132
- #
133
- # @example Dequeue a connection.
134
- # queue.dequeue
135
- #
136
- # @return [ Mongo::Server::Connection ] The next connection.
137
- # @raise [ Timeout::Error ] If the connection pool is at maximum size
138
- # and remains so for longer than the wait timeout.
139
- #
140
- # @since 2.0.0
141
- def dequeue
142
- check_count_invariants
143
- dequeue_connection
144
- ensure
145
- check_count_invariants
146
- end
147
-
148
- # Closes all idle connections in the queue and schedules currently
149
- # dequeued connections to be closed when they are enqueued back into
150
- # the queue. The queue remains operational and can create new
151
- # connections when requested.
152
- #
153
- # @example Disconnect all connections.
154
- # queue.disconnect!
155
- #
156
- # @return [ true ] Always true.
157
- #
158
- # @since 2.1.0
159
- def disconnect!
160
- check_count_invariants
161
- mutex.synchronize do
162
- while connection = queue.pop
163
- connection.disconnect!
164
- @pool_size -= 1
165
- if @pool_size < 0
166
- # This should never happen
167
- log_warn("ConnectionPool::Queue: connection accounting problem")
168
- @pool_size = 0
169
- end
170
- end
171
- @generation += 1
172
- true
173
- end
174
- ensure
175
- check_count_invariants
176
- end
177
-
178
- # Enqueue a connection in the queue.
179
- #
180
- # Only connections created by this queue should be enqueued
181
- # back into it, however the queue does not verify whether it
182
- # originally created the connection being enqueued.
183
- #
184
- # If linting is enabled (see Mongo::Lint), attempting to enqueue
185
- # connections beyond the pool's capacity will raise Mongo::Error::LintError
186
- # (since some of those connections must not have originated from
187
- # the queue into which they are being enqueued). If linting is
188
- # not enabled, the queue can grow beyond its max size with undefined
189
- # results.
190
- #
191
- # @example Enqueue a connection.
192
- # queue.enqueue(connection)
193
- #
194
- # @param [ Mongo::Server::Connection ] connection The connection.
195
- #
196
- # @since 2.0.0
197
- def enqueue(connection)
198
- check_count_invariants
199
- mutex.synchronize do
200
- if connection.generation == @generation
201
- queue.unshift(connection.record_checkin!)
202
- resource.broadcast
203
- else
204
- connection.disconnect!
205
-
206
- @pool_size = if @pool_size > 0
207
- @pool_size - 1
208
- else
209
- # This should never happen
210
- log_warn("ConnectionPool::Queue: unexpected enqueue")
211
- 0
212
- end
213
-
214
- while @pool_size < min_size
215
- @pool_size += 1
216
- queue.unshift(@block.call(@generation))
217
- end
218
- end
219
- end
220
- nil
221
- ensure
222
- check_count_invariants
223
- end
224
-
225
- # Get a pretty printed string inspection for the queue.
226
- #
227
- # @example Inspect the queue.
228
- # queue.inspect
229
- #
230
- # @return [ String ] The queue inspection.
231
- #
232
- # @since 2.0.0
233
- def inspect
234
- "#<Mongo::Server::ConnectionPool::Queue:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
235
- "wait_timeout=#{wait_timeout} current_size=#{queue_size}>"
236
- end
237
-
238
- # Get the maximum size of the connection pool.
239
- #
240
- # @example Get the max size.
241
- # queue.max_size
242
- #
243
- # @return [ Integer ] The maximum size of the connection pool.
244
- #
245
- # @since 2.0.0
246
- def max_size
247
- @max_size ||= options[:max_pool_size] || [MAX_SIZE, min_size].max
248
- end
249
-
250
- # Get the minimum size of the connection pool.
251
- #
252
- # @example Get the min size.
253
- # queue.min_size
254
- #
255
- # @return [ Integer ] The minimum size of the connection pool.
256
- #
257
- # @since 2.0.0
258
- def min_size
259
- @min_size ||= options[:min_pool_size] || MIN_SIZE
260
- end
261
-
262
- # The time to wait, in seconds, for a connection to become available.
263
- #
264
- # @example Get the wait timeout.
265
- # queue.wait_timeout
266
- #
267
- # @return [ Float ] The queue wait timeout.
268
- #
269
- # @since 2.0.0
270
- def wait_timeout
271
- @wait_timeout ||= options[:wait_queue_timeout] || WAIT_TIMEOUT
272
- end
273
-
274
- # The maximum seconds a socket can remain idle since it has been
275
- # checked in to the pool.
276
- #
277
- # @example Get the max idle time.
278
- # queue.max_idle_time
279
- #
280
- # @return [ Float ] The max socket idle time in seconds.
281
- #
282
- # @since 2.5.0
283
- def max_idle_time
284
- @max_idle_time ||= options[:max_idle_time]
285
- end
286
-
287
- # Close sockets that have been open for longer than the max idle time,
288
- # if the option is set.
289
- #
290
- # @example Close the stale sockets
291
- # queue.close_stale_sockets!
292
- #
293
- # @since 2.5.0
294
- def close_stale_sockets!
295
- check_count_invariants
296
- return unless max_idle_time
297
-
298
- mutex.synchronize do
299
- i = 0
300
- while i < queue.length
301
- connection = queue[i]
302
- if last_checkin = connection.last_checkin
303
- if (Time.now - last_checkin) > max_idle_time
304
- connection.disconnect!
305
- queue.delete_at(i)
306
- @pool_size -= 1
307
- next
308
- end
309
- end
310
- i += 1
311
- end
312
- end
313
- ensure
314
- check_count_invariants
315
- end
316
-
317
- private
318
-
319
- def dequeue_connection
320
- mutex.synchronize do
321
- deadline = Time.now + wait_timeout
322
- loop do
323
- return queue.shift unless queue.empty?
324
- connection = create_connection
325
- return connection if connection
326
- wait_for_next!(deadline)
327
- end
328
- end
329
- end
330
-
331
- def create_connection
332
- if pool_size < max_size
333
- @pool_size += 1
334
- @block.call(@generation)
335
- end
336
- end
337
-
338
- def wait_for_next!(deadline)
339
- wait = deadline - Time.now
340
- if wait <= 0
341
- raise Timeout::Error.new("Timed out attempting to dequeue connection after #{wait_timeout} sec.")
342
- end
343
- resource.wait(mutex, wait)
344
- end
345
-
346
- def check_count_invariants
347
- if Mongo::Lint.enabled?
348
- if pool_size < 0
349
- raise Error::LintError, 'connection pool queue: underflow'
350
- end
351
- if pool_size > max_size
352
- raise Error::LintError, 'connection pool queue: overflow'
353
- end
354
- end
355
- end
356
- end
357
- end
358
- end
359
- end
@@ -1,353 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mongo::Server::ConnectionPool::Queue do
4
-
5
- def create_connection(generation=-1)
6
- double('connection').tap do |connection|
7
- allow(connection).to receive(:generation).and_return(generation)
8
- allow(connection).to receive(:disconnect!)
9
- end
10
- end
11
-
12
- let(:connection) do
13
- create_connection
14
- end
15
-
16
- describe '#dequeue' do
17
-
18
- let(:queue) do
19
- described_class.new(:max_pool_size => 1) { connection }
20
- end
21
-
22
- context 'when the queue is empty' do
23
-
24
- context 'when the max size is reached' do
25
-
26
- it 'raises a timeout error' do
27
- expect {
28
- queue.dequeue
29
- queue.dequeue
30
- }.to raise_error(Timeout::Error)
31
- end
32
- end
33
-
34
- context 'when the max size is not reached' do
35
-
36
- it 'creates a new connection' do
37
- expect(queue.dequeue).to eq(connection)
38
- end
39
- end
40
- end
41
-
42
- context 'when waiting for a connection to be enqueued' do
43
-
44
- before do
45
- allow(connection).to receive(:record_checkin!).and_return(connection)
46
- Thread.new do
47
- sleep(0.5)
48
- queue.enqueue(connection)
49
- end.join
50
- end
51
-
52
- it 'returns the enqueued connection' do
53
- expect(queue.dequeue).to eq(connection)
54
- end
55
- end
56
- end
57
-
58
- describe '#disconnect!' do
59
-
60
- def create_queue(min_pool_size)
61
- described_class.new(max_pool_size: 3, min_pool_size: min_pool_size) do |generation|
62
- create_connection(generation)
63
- end.tap do |queue|
64
- # make queue be of size 2 so that it has enqueued connections
65
- # when told to disconnect
66
- c1 = queue.dequeue
67
- c2 = queue.dequeue
68
- allow(c1).to receive(:record_checkin!).and_return(c1)
69
- allow(c2).to receive(:record_checkin!).and_return(c2)
70
- queue.enqueue(c1)
71
- queue.enqueue(c2)
72
- expect(queue.queue_size).to eq(2)
73
- expect(queue.pool_size).to eq(2)
74
- end
75
- end
76
-
77
- context 'min size is 0' do
78
- let(:queue) do
79
- create_queue(0)
80
- end
81
-
82
- it 'disconnects and removes all connections in the queue' do
83
- queue.queue.each do |connection|
84
- expect(connection).to receive(:disconnect!)
85
- end
86
- expect(queue.queue_size).to eq(2)
87
- expect(queue.pool_size).to eq(2)
88
- queue.disconnect!
89
- expect(queue.queue_size).to eq(0)
90
- expect(queue.pool_size).to eq(0)
91
- end
92
- end
93
-
94
- context 'min size is not 0' do
95
- let(:queue) do
96
- create_queue(1)
97
- end
98
-
99
- it 'disconnects all connections in the queue and bumps generation' do
100
- expect(queue.queue_size).to eq(2)
101
- expect(queue.pool_size).to eq(2)
102
-
103
- queue.disconnect!
104
-
105
- expect(queue.queue_size).to eq(0)
106
- expect(queue.pool_size).to eq(0)
107
-
108
- new_connection = queue.dequeue
109
- expect(new_connection).not_to eq(connection)
110
- expect(new_connection.generation).to eq(2)
111
- end
112
- end
113
- end
114
-
115
- describe '#enqueue' do
116
-
117
- let(:connection) do
118
- queue.dequeue.tap do |connection|
119
- allow(connection).to receive(:generation).and_return(1)
120
- allow(connection).to receive(:record_checkin!).and_return(connection)
121
- end
122
- end
123
-
124
- let(:queue) do
125
- # max pool size set to 2 to allow enqueueing a connection
126
- # without lint violations
127
- described_class.new(:max_pool_size => 2) { create_connection }
128
- end
129
-
130
- context 'connection of the same generation as queue' do
131
- before do
132
- expect(queue.generation).to eq(connection.generation)
133
- end
134
-
135
- it 'adds the connection to the queue' do
136
- # connection is checked out
137
- expect(queue.queue_size).to eq(0)
138
- expect(queue.pool_size).to eq(1)
139
- queue.enqueue(connection)
140
- # now connection is in the queue
141
- expect(queue.queue_size).to eq(1)
142
- expect(queue.pool_size).to eq(1)
143
- expect(queue.dequeue).to eq(connection)
144
- end
145
- end
146
-
147
- shared_examples 'does not add connection to queue' do
148
- before do
149
- expect(queue.generation).not_to eq(connection.generation)
150
- end
151
-
152
- it 'disconnects connection and does not add connection to queue' do
153
- # connection was checked out
154
- expect(queue.queue_size).to eq(0)
155
- expect(queue.pool_size).to eq(1)
156
- expect(connection).to receive(:disconnect!)
157
- queue.enqueue(connection)
158
- expect(queue.queue_size).to eq(1)
159
- expect(queue.pool_size).to eq(1)
160
- expect(queue.dequeue).not_to eq(connection)
161
- end
162
- end
163
-
164
- context 'connection of earlier generation than queue' do
165
- let(:connection) do
166
- queue.dequeue.tap do |connection|
167
- allow(connection).to receive(:generation).and_return(0)
168
- allow(connection).to receive(:record_checkin!).and_return(connection)
169
- end
170
- end
171
-
172
- it_behaves_like 'does not add connection to queue'
173
- end
174
-
175
- context 'connection of later generation than queue' do
176
- let(:connection) do
177
- queue.dequeue.tap do |connection|
178
- allow(connection).to receive(:generation).and_return(7)
179
- allow(connection).to receive(:record_checkin!).and_return(connection)
180
- end
181
- end
182
-
183
- it_behaves_like 'does not add connection to queue'
184
- end
185
- end
186
-
187
- describe '#initialize' do
188
-
189
- context 'when a min size is provided' do
190
-
191
- let(:queue) do
192
- described_class.new(:min_pool_size => 2) { create_connection }
193
- end
194
-
195
- it 'creates the queue with the minimum connections' do
196
- expect(queue.pool_size).to eq(2)
197
- expect(queue.queue_size).to eq(2)
198
- end
199
-
200
- it 'does not use the same objects in the queue' do
201
- expect(queue.dequeue).to_not equal(queue.dequeue)
202
- end
203
- end
204
-
205
- context 'when min size exceeds default max size' do
206
-
207
- let(:queue) do
208
- described_class.new(:min_pool_size => 10) { create_connection }
209
- end
210
-
211
- it 'sets max size to equal provided min size' do
212
- expect(queue.max_size).to eq(10)
213
- end
214
- end
215
-
216
- context 'when no min size is provided' do
217
-
218
- let(:queue) do
219
- described_class.new { create_connection }
220
- end
221
-
222
- it 'creates the queue with the number of default connections' do
223
- expect(queue.pool_size).to eq(1)
224
- expect(queue.queue_size).to eq(1)
225
- end
226
- end
227
- end
228
-
229
- describe '#inspect' do
230
-
231
- let(:queue) do
232
- described_class.new(:min_pool_size => 2) { create_connection }
233
- end
234
-
235
- it 'includes the object id' do
236
- expect(queue.inspect).to include(queue.object_id.to_s)
237
- end
238
-
239
- it 'includes the min size' do
240
- expect(queue.inspect).to include('min_size=2')
241
- end
242
-
243
- it 'includes the max size' do
244
- expect(queue.inspect).to include('max_size=5')
245
- end
246
-
247
- it 'includes the wait timeout' do
248
- expect(queue.inspect).to include('wait_timeout=1')
249
- end
250
-
251
- it 'includes the current size' do
252
- expect(queue.inspect).to include('current_size=2')
253
- end
254
- end
255
-
256
- describe '#max_size' do
257
-
258
- context 'when a max pool size option is provided' do
259
-
260
- let(:queue) do
261
- described_class.new(:max_pool_size => 3) { create_connection }
262
- end
263
-
264
- it 'returns the max size' do
265
- expect(queue.max_size).to eq(3)
266
- end
267
- end
268
-
269
- context 'when no pool size option is provided' do
270
-
271
- let(:queue) do
272
- described_class.new { create_connection }
273
- end
274
-
275
- it 'returns the default size' do
276
- expect(queue.max_size).to eq(5)
277
- end
278
- end
279
- end
280
-
281
- describe '#wait_timeout' do
282
-
283
- context 'when the wait timeout option is provided' do
284
-
285
- let(:queue) do
286
- described_class.new(:wait_queue_timeout => 3) { create_connection }
287
- end
288
-
289
- it 'returns the wait timeout' do
290
- expect(queue.wait_timeout).to eq(3)
291
- end
292
- end
293
-
294
- context 'when the wait timeout option is not provided' do
295
-
296
- let(:queue) do
297
- described_class.new { create_connection }
298
- end
299
-
300
- it 'returns the default wait timeout' do
301
- expect(queue.wait_timeout).to eq(1)
302
- end
303
- end
304
- end
305
-
306
- describe 'close_stale_sockets!!' do
307
- after do
308
- Timecop.return
309
- end
310
-
311
- let(:queue) do
312
- described_class.new(max_pool_size: 2, max_idle_time: 0.5) do
313
- double('connection').tap do |con|
314
- expect(con).to receive(:generation).and_return(1)
315
- allow(con).to receive(:record_checkin!) do
316
- allow(con).to receive(:last_checkin).and_return(Time.now)
317
- con
318
- end
319
- end
320
- end
321
- end
322
-
323
- let(:connection) do
324
- queue.dequeue.tap do |con|
325
- allow(con).to receive(:disconnect!)
326
- end
327
- end
328
-
329
- it 'disconnects all expired and only expired connections' do
330
- c1 = queue.dequeue
331
- expect(c1).to receive(:disconnect!)
332
- c2 = queue.dequeue
333
- expect(c2).not_to receive(:disconnect!)
334
-
335
- queue.enqueue(c1)
336
- Timecop.travel(Time.now + 1)
337
- queue.enqueue(c2)
338
-
339
- expect(queue.queue_size).to eq(2)
340
- expect(queue.pool_size).to eq(2)
341
- expect(queue.queue.length).to eq(2)
342
-
343
- expect(c1).not_to receive(:connect!)
344
- expect(c2).not_to receive(:connect!)
345
-
346
- queue.close_stale_sockets!
347
-
348
- expect(queue.queue_size).to eq(1)
349
- expect(queue.pool_size).to eq(1)
350
- expect(queue.queue.length).to eq(1)
351
- end
352
- end
353
- end