mongo 2.8.0 → 2.9.0.rc0

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