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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Rakefile +12 -0
- data/lib/mongo.rb +15 -1
- data/lib/mongo/address/ipv6.rb +0 -2
- data/lib/mongo/auth/scram/conversation.rb +0 -3
- data/lib/mongo/bulk_write/result_combiner.rb +12 -2
- data/lib/mongo/client.rb +59 -6
- data/lib/mongo/cluster.rb +19 -8
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +0 -2
- data/lib/mongo/cluster/reapers/socket_reaper.rb +12 -9
- data/lib/mongo/collection.rb +1 -1
- data/lib/mongo/collection/view/aggregation.rb +5 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +30 -10
- data/lib/mongo/collection/view/iterable.rb +13 -6
- data/lib/mongo/collection/view/map_reduce.rb +12 -10
- data/lib/mongo/collection/view/readable.rb +19 -14
- data/lib/mongo/cursor.rb +12 -8
- data/lib/mongo/database.rb +10 -7
- data/lib/mongo/database/view.rb +18 -11
- data/lib/mongo/error.rb +2 -2
- data/lib/mongo/error/connection_check_out_timeout.rb +49 -0
- data/lib/mongo/error/operation_failure.rb +9 -9
- data/lib/mongo/error/parser.rb +25 -3
- data/lib/mongo/error/pool_closed_error.rb +43 -0
- data/lib/mongo/error/sdam_error_detection.rb +18 -0
- data/lib/mongo/grid/file/chunk.rb +0 -2
- data/lib/mongo/grid/fs_bucket.rb +26 -12
- data/lib/mongo/grid/stream/read.rb +36 -21
- data/lib/mongo/index/view.rb +11 -7
- data/lib/mongo/logger.rb +0 -2
- data/lib/mongo/monitoring.rb +31 -0
- data/lib/mongo/monitoring/cmap_log_subscriber.rb +53 -0
- data/lib/mongo/monitoring/event.rb +1 -0
- data/lib/mongo/monitoring/event/cmap.rb +25 -0
- data/lib/mongo/monitoring/event/cmap/base.rb +28 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +78 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +56 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +63 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +64 -0
- data/lib/mongo/monitoring/event/cmap/connection_closed.rb +103 -0
- data/lib/mongo/monitoring/event/cmap/connection_created.rb +64 -0
- data/lib/mongo/monitoring/event/cmap/connection_ready.rb +64 -0
- data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +57 -0
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +57 -0
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +63 -0
- data/lib/mongo/monitoring/event/command_started.rb +12 -3
- data/lib/mongo/monitoring/publishable.rb +10 -2
- data/lib/mongo/operation.rb +0 -1
- data/lib/mongo/operation/find/legacy/result.rb +1 -0
- data/lib/mongo/operation/list_collections/result.rb +7 -1
- data/lib/mongo/operation/result.rb +10 -1
- data/lib/mongo/operation/shared/executable.rb +15 -0
- data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +29 -0
- data/lib/mongo/operation/shared/specifiable.rb +0 -16
- data/lib/mongo/operation/update/legacy/result.rb +1 -0
- data/lib/mongo/protocol/compressed.rb +0 -2
- data/lib/mongo/protocol/msg.rb +25 -2
- data/lib/mongo/retryable.rb +171 -33
- data/lib/mongo/server.rb +26 -7
- data/lib/mongo/server/app_metadata.rb +0 -2
- data/lib/mongo/server/connectable.rb +8 -2
- data/lib/mongo/server/connection.rb +83 -13
- data/lib/mongo/server/connection_base.rb +1 -1
- data/lib/mongo/server/connection_pool.rb +439 -43
- data/lib/mongo/server/monitor/connection.rb +4 -1
- data/lib/mongo/session.rb +37 -5
- data/lib/mongo/session/session_pool.rb +2 -2
- data/lib/mongo/socket.rb +0 -2
- data/lib/mongo/socket/ssl.rb +0 -2
- data/lib/mongo/uri.rb +127 -66
- data/lib/mongo/uri/srv_protocol.rb +35 -13
- data/lib/mongo/version.rb +1 -1
- data/spec/README.md +190 -63
- data/spec/integration/change_stream_spec.rb +64 -0
- data/spec/integration/command_spec.rb +0 -7
- data/spec/integration/error_detection_spec.rb +39 -0
- data/spec/integration/read_concern.rb +83 -0
- data/spec/integration/retryable_writes_spec.rb +6 -50
- data/spec/integration/sdam_error_handling_spec.rb +60 -7
- data/spec/integration/ssl_uri_options_spec.rb +24 -0
- data/spec/integration/step_down_spec.rb +197 -0
- data/spec/lite_spec_helper.rb +4 -0
- data/spec/mongo/client_construction_spec.rb +42 -17
- data/spec/mongo/client_spec.rb +32 -1
- data/spec/mongo/cluster/socket_reaper_spec.rb +2 -2
- data/spec/mongo/cluster_spec.rb +36 -2
- data/spec/mongo/collection/view/aggregation_spec.rb +2 -0
- data/spec/mongo/collection/view/change_stream_spec.rb +28 -28
- data/spec/mongo/collection/view/readable_spec.rb +1 -1
- data/spec/mongo/collection/view_spec.rb +3 -1
- data/spec/mongo/cursor_spec.rb +5 -5
- data/spec/mongo/error/parser_spec.rb +61 -1
- data/spec/mongo/grid/stream/read_spec.rb +2 -2
- data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +23 -0
- data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +19 -0
- data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +23 -0
- data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +23 -0
- data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +27 -0
- data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +24 -0
- data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +24 -0
- data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +19 -0
- data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +19 -0
- data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +26 -0
- data/spec/mongo/operation/delete/bulk_spec.rb +1 -6
- data/spec/mongo/operation/delete/command_spec.rb +1 -1
- data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
- data/spec/mongo/operation/delete_spec.rb +4 -4
- data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
- data/spec/mongo/operation/insert/command_spec.rb +1 -1
- data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
- data/spec/mongo/operation/update/bulk_spec.rb +1 -1
- data/spec/mongo/operation/update/command_spec.rb +2 -2
- data/spec/mongo/operation/update/op_msg_spec.rb +2 -2
- data/spec/mongo/protocol/msg_spec.rb +11 -0
- data/spec/mongo/retryable_spec.rb +78 -25
- data/spec/mongo/server/connection_pool_spec.rb +661 -126
- data/spec/mongo/server/connection_spec.rb +55 -7
- data/spec/mongo/server_spec.rb +5 -0
- data/spec/mongo/uri/srv_protocol_spec.rb +135 -2
- data/spec/mongo/uri_option_parsing_spec.rb +511 -0
- data/spec/mongo/uri_spec.rb +42 -6
- data/spec/spec_helper.rb +1 -84
- data/spec/spec_tests/cmap_spec.rb +50 -0
- data/spec/spec_tests/command_monitoring_spec.rb +7 -18
- data/spec/spec_tests/crud_spec.rb +3 -49
- data/spec/spec_tests/data/cmap/connection-must-have-id.yml +21 -0
- data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +21 -0
- data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +24 -0
- data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +24 -0
- data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +21 -0
- data/spec/spec_tests/data/cmap/pool-checkin.yml +18 -0
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +13 -0
- data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +28 -0
- data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +34 -0
- data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +31 -0
- data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +29 -0
- data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +26 -0
- data/spec/spec_tests/data/cmap/pool-close.yml +11 -0
- data/spec/spec_tests/data/cmap/pool-create-max-size.yml +56 -0
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +27 -0
- data/spec/spec_tests/data/cmap/pool-create-with-options.yml +20 -0
- data/spec/spec_tests/data/cmap/pool-create.yml +12 -0
- data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +94 -0
- data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +41 -0
- data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +157 -0
- data/spec/spec_tests/data/retryable_reads/aggregate.yml +87 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +149 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +61 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +149 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +65 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +153 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +61 -0
- data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +150 -0
- data/spec/spec_tests/data/retryable_reads/count.yml +64 -0
- data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +150 -0
- data/spec/spec_tests/data/retryable_reads/countDocuments.yml +64 -0
- data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +156 -0
- data/spec/spec_tests/data/retryable_reads/distinct.yml +71 -0
- data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +148 -0
- data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount.yml +62 -0
- data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +160 -0
- data/spec/spec_tests/data/retryable_reads/find.yml +86 -0
- data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +154 -0
- data/spec/spec_tests/data/retryable_reads/findOne.yml +68 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +173 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-download.yml +79 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +174 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName.yml +79 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +143 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionNames.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionObjects.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +143 -0
- data/spec/spec_tests/data/retryable_reads/listCollections.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +143 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseNames.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseObjects.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listDatabases.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +60 -0
- data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +145 -0
- data/spec/spec_tests/data/retryable_reads/listIndexes.yml +60 -0
- data/spec/spec_tests/data/retryable_reads/mapReduce.yml +60 -0
- data/spec/spec_tests/data/retryable_writes/bulkWrite-serverErrors.yml +10 -7
- data/spec/spec_tests/data/retryable_writes/bulkWrite.yml +15 -22
- data/spec/spec_tests/data/retryable_writes/deleteMany.yml +22 -0
- data/spec/spec_tests/data/retryable_writes/deleteOne-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/deleteOne.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/findOneAndDelete-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/findOneAndDelete.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/findOneAndReplace-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/findOneAndReplace.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/findOneAndUpdate.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/insertMany-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/insertMany.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +10 -45
- data/spec/spec_tests/data/retryable_writes/insertOne.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/replaceOne-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/replaceOne.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/updateMany.yml +27 -0
- data/spec/spec_tests/data/retryable_writes/updateOne-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/updateOne.yml +5 -14
- data/spec/spec_tests/data/transactions/abort.yml +7 -2
- data/spec/spec_tests/data/transactions/bulk.yml +7 -2
- data/spec/spec_tests/data/transactions/causal-consistency.yml +11 -4
- data/spec/spec_tests/data/transactions/commit.yml +11 -4
- data/spec/spec_tests/data/transactions/count.yml +64 -0
- data/spec/spec_tests/data/transactions/delete.yml +7 -2
- data/spec/spec_tests/data/transactions/error-labels.yml +8 -2
- data/spec/spec_tests/data/transactions/errors.yml +7 -2
- data/spec/spec_tests/data/transactions/findOneAndDelete.yml +7 -2
- data/spec/spec_tests/data/transactions/findOneAndReplace.yml +7 -2
- data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +7 -2
- data/spec/spec_tests/data/transactions/insert.yml +9 -2
- data/spec/spec_tests/data/transactions/isolation.yml +7 -2
- data/spec/spec_tests/data/transactions/read-concern.yml +15 -6
- data/spec/spec_tests/data/transactions/read-pref.yml +7 -2
- data/spec/spec_tests/data/transactions/reads.yml +8 -48
- data/spec/spec_tests/data/transactions/retryable-abort.yml +7 -2
- data/spec/spec_tests/data/transactions/retryable-commit.yml +7 -2
- data/spec/spec_tests/data/transactions/retryable-writes.yml +7 -2
- data/spec/spec_tests/data/transactions/run-command.yml +7 -2
- data/spec/spec_tests/data/transactions/transaction-options.yml +7 -2
- data/spec/spec_tests/data/transactions/update.yml +7 -2
- data/spec/spec_tests/data/transactions/write-concern.yml +7 -2
- data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -1
- data/spec/spec_tests/data/transactions_api/callback-commits.yml +6 -1
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit-retry.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +6 -3
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit.yml +6 -1
- data/spec/spec_tests/data/transactions_api/transaction-options.yml +6 -1
- data/spec/spec_tests/retryable_reads_spec.rb +11 -0
- data/spec/spec_tests/retryable_writes_spec.rb +4 -69
- data/spec/spec_tests/transactions_api_spec.rb +42 -37
- data/spec/spec_tests/transactions_spec.rb +42 -33
- data/spec/support/authorization.rb +12 -0
- data/spec/support/change_streams/operation.rb +1 -1
- data/spec/support/client_registry.rb +20 -0
- data/spec/support/cluster_config.rb +16 -15
- data/spec/support/cluster_tools.rb +346 -0
- data/spec/support/cmap.rb +367 -0
- data/spec/support/cmap/verifier.rb +46 -0
- data/spec/support/command_monitoring.rb +4 -6
- data/spec/support/common_shortcuts.rb +6 -0
- data/spec/support/connection_string.rb +2 -2
- data/spec/support/crud.rb +171 -184
- data/spec/support/crud/operation.rb +43 -0
- data/spec/support/crud/outcome.rb +53 -0
- data/spec/support/crud/read.rb +102 -12
- data/spec/support/crud/requirement.rb +69 -0
- data/spec/support/crud/spec.rb +68 -0
- data/spec/support/crud/test.rb +141 -0
- data/spec/support/crud/verifier.rb +96 -18
- data/spec/support/crud/write.rb +18 -3
- data/spec/support/event_subscriber.rb +15 -0
- data/spec/support/primary_socket.rb +2 -2
- data/spec/support/spec_config.rb +89 -20
- data/spec/support/transactions.rb +2 -306
- data/spec/support/transactions/operation.rb +7 -7
- data/spec/support/transactions/spec.rb +28 -0
- data/spec/support/transactions/test.rb +191 -0
- data/spec/support/utils.rb +123 -0
- metadata +202 -9
- metadata.gz.sig +0 -0
- data/lib/mongo/server/connection_pool/queue.rb +0 -359
- data/spec/mongo/server/connection_pool/queue_spec.rb +0 -353
- data/spec/support/transactions/verifier.rb +0 -97
@@ -96,7 +96,7 @@ module Mongo
|
|
96
96
|
buffer = serialize(message)
|
97
97
|
ensure_connected do |socket|
|
98
98
|
operation_id = Monitoring.next_operation_id
|
99
|
-
command_started(address, operation_id, message.payload)
|
99
|
+
command_started(address, operation_id, message.payload, socket.object_id)
|
100
100
|
start = Time.now
|
101
101
|
result = nil
|
102
102
|
begin
|
@@ -12,73 +12,346 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require 'mongo/server/connection_pool/queue'
|
16
|
-
|
17
15
|
module Mongo
|
18
16
|
class Server
|
19
17
|
|
20
18
|
# Represents a connection pool for server connections.
|
21
19
|
#
|
22
|
-
# @since 2.0.0
|
20
|
+
# @since 2.0.0, largely rewritten in 2.9.0
|
23
21
|
class ConnectionPool
|
24
22
|
include Loggable
|
23
|
+
include Monitoring::Publishable
|
25
24
|
extend Forwardable
|
26
25
|
|
27
|
-
#
|
26
|
+
# The default max size for the connection pool.
|
28
27
|
#
|
29
|
-
# @
|
30
|
-
|
31
|
-
|
32
|
-
#
|
28
|
+
# @since 2.9.0
|
29
|
+
DEFAULT_MAX_SIZE = 5.freeze
|
30
|
+
|
31
|
+
# The default min size for the connection pool.
|
33
32
|
#
|
34
|
-
# @
|
33
|
+
# @since 2.9.0
|
34
|
+
DEFAULT_MIN_SIZE = 0.freeze
|
35
|
+
|
36
|
+
# The default timeout, in seconds, to wait for a connection.
|
37
|
+
#
|
38
|
+
# @since 2.9.0
|
39
|
+
DEFAULT_WAIT_TIMEOUT = 1.freeze
|
40
|
+
|
41
|
+
# Create the new connection pool.
|
35
42
|
#
|
43
|
+
# @param [ Server ] server The server which this connection pool is for.
|
36
44
|
# @param [ Hash ] options The connection pool options.
|
37
45
|
#
|
38
|
-
# @option options [ Integer ] :
|
39
|
-
# @option options [ Integer ] :
|
40
|
-
#
|
46
|
+
# @option options [ Integer ] :max_size The maximum pool size.
|
47
|
+
# @option options [ Integer ] :max_pool_size Deprecated.
|
48
|
+
# The maximum pool size. If max_size is also given, max_size and
|
49
|
+
# max_pool_size must be identical.
|
50
|
+
# @option options [ Integer ] :min_size The minimum pool size.
|
51
|
+
# @option options [ Integer ] :min_pool_size Deprecated.
|
52
|
+
# The minimum pool size. If min_size is also given, min_size and
|
53
|
+
# min_pool_size must be identical.
|
54
|
+
# @option options [ Float ] :wait_timeout The time to wait, in
|
41
55
|
# seconds, for a free connection.
|
56
|
+
# @option options [ Float ] :wait_queue_timeout Deprecated.
|
57
|
+
# Alias for :wait_timeout. If both wait_timeout and wait_queue_timeout
|
58
|
+
# are given, their values must be identical.
|
59
|
+
# @option options [ Float ] :max_idle_time The time, in seconds,
|
60
|
+
# after which idle connections should be closed by the pool.
|
42
61
|
#
|
43
|
-
# @since 2.0.0
|
44
|
-
def initialize(options = {}
|
45
|
-
|
46
|
-
|
62
|
+
# @since 2.0.0, API changed in 2.9.0
|
63
|
+
def initialize(server, options = {})
|
64
|
+
unless server.is_a?(Server)
|
65
|
+
raise ArgumentError, 'First argument must be a Server instance'
|
66
|
+
end
|
67
|
+
options = options.dup
|
68
|
+
if options[:min_size] && options[:min_pool_size] && options[:min_size] != options[:min_pool_size]
|
69
|
+
raise ArgumentError, "Min size #{options[:min_size]} is not identical to min pool size #{options[:min_pool_size]}"
|
70
|
+
end
|
71
|
+
if options[:max_size] && options[:max_pool_size] && options[:max_size] != options[:max_pool_size]
|
72
|
+
raise ArgumentError, "Max size #{options[:max_size]} is not identical to max pool size #{options[:max_pool_size]}"
|
73
|
+
end
|
74
|
+
if options[:wait_timeout] && options[:wait_queue_timeout] && options[:wait_timeout] != options[:wait_queue_timeout]
|
75
|
+
raise ArgumentError, "Wait timeout #{options[:wait_timeout]} is not identical to wait queue timeout #{options[:wait_queue_timeout]}"
|
76
|
+
end
|
77
|
+
options[:min_size] ||= options[:min_pool_size]
|
78
|
+
options.delete(:min_pool_size)
|
79
|
+
options[:max_size] ||= options[:max_pool_size]
|
80
|
+
options.delete(:max_pool_size)
|
81
|
+
if options[:min_size] && options[:max_size] &&
|
82
|
+
options[:min_size] > options[:max_size]
|
83
|
+
then
|
84
|
+
raise ArgumentError, "Cannot have min size #{options[:min_size]} exceed max size #{options[:max_size]}"
|
85
|
+
end
|
86
|
+
if options[:wait_queue_timeout]
|
87
|
+
options[:wait_timeout] ||= options[:wait_queue_timeout]
|
88
|
+
end
|
89
|
+
options.delete(:wait_queue_timeout)
|
90
|
+
|
91
|
+
@server = server
|
92
|
+
@options = options.freeze
|
93
|
+
|
94
|
+
@generation = 1
|
95
|
+
@closed = false
|
96
|
+
|
97
|
+
# A connection owned by this pool should be either in the
|
98
|
+
# available connections array (which is used as a stack)
|
99
|
+
# or in the checked out connections set.
|
100
|
+
@available_connections = available_connections = []
|
101
|
+
@checked_out_connections = Set.new
|
102
|
+
|
103
|
+
# Mutex used for synchronizing access to @available_connections and
|
104
|
+
# @checked_out_connections. The pool object is thread-safe, thus
|
105
|
+
# all methods that retrieve or modify instance variables generally
|
106
|
+
# must do so under this lock.
|
107
|
+
@lock = Mutex.new
|
108
|
+
|
109
|
+
# Condition variable broadcast when a connection is added to
|
110
|
+
# @available_connections, to wake up any threads waiting for an
|
111
|
+
# available connection when pool is at max size
|
112
|
+
@available_semaphore = Semaphore.new
|
47
113
|
|
48
114
|
finalizer = proc do
|
49
|
-
|
115
|
+
available_connections.each do |connection|
|
116
|
+
connection.disconnect!(reason: :pool_closed)
|
117
|
+
end
|
118
|
+
available_connections.clear
|
119
|
+
# Finalizer does not close checked out connections.
|
120
|
+
# Those would have to be garbage collected on their own
|
121
|
+
# and that should close them.
|
50
122
|
end
|
51
123
|
ObjectSpace.define_finalizer(self, finalizer)
|
124
|
+
|
125
|
+
publish_cmap_event(
|
126
|
+
Monitoring::Event::Cmap::PoolCreated.new(@server.address, options)
|
127
|
+
)
|
52
128
|
end
|
53
129
|
|
54
130
|
# @return [ Hash ] options The pool options.
|
55
131
|
attr_reader :options
|
56
132
|
|
57
|
-
|
133
|
+
# Get the maximum size of the connection pool.
|
134
|
+
#
|
135
|
+
# @return [ Integer ] The maximum size of the connection pool.
|
136
|
+
#
|
137
|
+
# @since 2.9.0
|
138
|
+
def max_size
|
139
|
+
@max_size ||= options[:max_size] || [DEFAULT_MAX_SIZE, min_size].max
|
140
|
+
end
|
141
|
+
|
142
|
+
# Get the minimum size of the connection pool.
|
143
|
+
#
|
144
|
+
# @return [ Integer ] The minimum size of the connection pool.
|
145
|
+
#
|
146
|
+
# @since 2.9.0
|
147
|
+
def min_size
|
148
|
+
@min_size ||= options[:min_size] || DEFAULT_MIN_SIZE
|
149
|
+
end
|
58
150
|
|
59
|
-
#
|
60
|
-
# thread local stack that should contain it after it was checked out.
|
151
|
+
# The time to wait, in seconds, for a connection to become available.
|
61
152
|
#
|
62
|
-
# @
|
63
|
-
# pool.checkin
|
153
|
+
# @return [ Float ] The queue wait timeout.
|
64
154
|
#
|
65
|
-
# @since 2.
|
66
|
-
def
|
67
|
-
|
155
|
+
# @since 2.9.0
|
156
|
+
def wait_timeout
|
157
|
+
@wait_timeout ||= options[:wait_timeout] || DEFAULT_WAIT_TIMEOUT
|
68
158
|
end
|
69
159
|
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# connection from the queue and pin it to this thread.
|
160
|
+
# The maximum seconds a socket can remain idle since it has been
|
161
|
+
# checked in to the pool, if set.
|
73
162
|
#
|
74
|
-
# @
|
75
|
-
#
|
163
|
+
# @return [ Float | nil ] The max socket idle time in seconds.
|
164
|
+
#
|
165
|
+
# @since 2.9.0
|
166
|
+
def max_idle_time
|
167
|
+
@max_idle_time ||= options[:max_idle_time]
|
168
|
+
end
|
169
|
+
|
170
|
+
# @return [ Integer ] generation Generation of connections currently
|
171
|
+
# being used by the queue.
|
172
|
+
#
|
173
|
+
# @since 2.9.0
|
174
|
+
# @api private
|
175
|
+
attr_reader :generation
|
176
|
+
|
177
|
+
# Size of the connection pool.
|
178
|
+
#
|
179
|
+
# Includes available and checked out connections.
|
180
|
+
#
|
181
|
+
# @return [ Integer ] Size of the connection pool.
|
182
|
+
#
|
183
|
+
# @since 2.9.0
|
184
|
+
def size
|
185
|
+
raise_if_closed!
|
186
|
+
|
187
|
+
@lock.synchronize do
|
188
|
+
unsynchronized_size
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns the size of the connection pool without acquiring the lock.
|
193
|
+
# This method should only be used by other pool methods when they are
|
194
|
+
# already holding the lock as Ruby does not allow a thread holding a
|
195
|
+
# lock to acquire this lock again.
|
196
|
+
def unsynchronized_size
|
197
|
+
@available_connections.length + @checked_out_connections.size
|
198
|
+
end
|
199
|
+
private :unsynchronized_size
|
200
|
+
|
201
|
+
# Number of available connections in the pool.
|
202
|
+
#
|
203
|
+
# @return [ Integer ] Number of available connections.
|
204
|
+
#
|
205
|
+
# @since 2.9.0
|
206
|
+
def available_count
|
207
|
+
raise_if_closed!
|
208
|
+
|
209
|
+
@lock.synchronize do
|
210
|
+
@available_connections.length
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Whether the pool has been closed.
|
215
|
+
#
|
216
|
+
# @return [ true | false ] Whether the pool is closed.
|
217
|
+
#
|
218
|
+
# @since 2.9.0
|
219
|
+
def closed?
|
220
|
+
!!@closed
|
221
|
+
end
|
222
|
+
|
223
|
+
# @since 2.9.0
|
224
|
+
def_delegators :@server, :monitoring
|
225
|
+
|
226
|
+
# Checks a connection out of the pool.
|
227
|
+
#
|
228
|
+
# If there are active connections in the pool, the most recently used
|
229
|
+
# connection is returned. Otherwise if the connection pool size is less
|
230
|
+
# than the max size, creates a new connection and returns it. Otherwise
|
231
|
+
# waits up to the wait timeout and raises Timeout::Error if there are
|
232
|
+
# still no active connections and the pool is at max size.
|
233
|
+
#
|
234
|
+
# The returned connection counts toward the pool's max size. When the
|
235
|
+
# caller is finished using the connection, the connection should be
|
236
|
+
# checked back in via the check_in method.
|
76
237
|
#
|
77
238
|
# @return [ Mongo::Server::Connection ] The checked out connection.
|
239
|
+
# @raise [ Timeout::Error ] If the connection pool is at maximum size
|
240
|
+
# and remains so for longer than the wait timeout.
|
78
241
|
#
|
79
|
-
# @since 2.
|
80
|
-
def
|
81
|
-
|
242
|
+
# @since 2.9.0
|
243
|
+
def check_out
|
244
|
+
raise_if_closed!
|
245
|
+
|
246
|
+
publish_cmap_event(
|
247
|
+
Monitoring::Event::Cmap::ConnectionCheckOutStarted.new(@server.address)
|
248
|
+
)
|
249
|
+
|
250
|
+
deadline = Time.now + wait_timeout
|
251
|
+
connection = nil
|
252
|
+
# It seems that synchronize sets up its own loop, thus a simple break
|
253
|
+
# is insufficient to break the outer loop
|
254
|
+
catch(:done) do
|
255
|
+
loop do
|
256
|
+
# Lock must be taken on each iteration, rather for the method
|
257
|
+
# overall, otherwise other threads will not be able to check in
|
258
|
+
# a connection while this thread is waiting for one.
|
259
|
+
@lock.synchronize do
|
260
|
+
until @available_connections.empty?
|
261
|
+
connection = @available_connections.pop
|
262
|
+
|
263
|
+
if connection.generation != generation
|
264
|
+
# Stale connections should be disconnected in the clear
|
265
|
+
# method, but if any don't, check again here
|
266
|
+
connection.disconnect!(reason: :stale)
|
267
|
+
next
|
268
|
+
end
|
269
|
+
|
270
|
+
if max_idle_time && connection.last_checkin &&
|
271
|
+
Time.now - connection.last_checkin > max_idle_time
|
272
|
+
then
|
273
|
+
connection.disconnect!(reason: :idle)
|
274
|
+
next
|
275
|
+
end
|
276
|
+
|
277
|
+
throw(:done)
|
278
|
+
end
|
279
|
+
|
280
|
+
# Ruby does not allow a thread to lock a mutex which it already
|
281
|
+
# holds.
|
282
|
+
if unsynchronized_size < max_size
|
283
|
+
# This does not currently connect the socket and handshake,
|
284
|
+
# but if it did, it would be performing i/o under our lock,
|
285
|
+
# which is bad. Fix in the future.
|
286
|
+
connection = create_connection
|
287
|
+
throw(:done)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
wait = deadline - Time.now
|
292
|
+
if wait <= 0
|
293
|
+
publish_cmap_event(
|
294
|
+
Monitoring::Event::Cmap::ConnectionCheckOutFailed.new(
|
295
|
+
@server.address,
|
296
|
+
Monitoring::Event::Cmap::ConnectionCheckOutFailed::TIMEOUT,
|
297
|
+
),
|
298
|
+
)
|
299
|
+
raise Error::ConnectionCheckOutTimeout.new(@server.address, wait_timeout)
|
300
|
+
end
|
301
|
+
@available_semaphore.wait(wait)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
@checked_out_connections << connection
|
306
|
+
publish_cmap_event(
|
307
|
+
Monitoring::Event::Cmap::ConnectionCheckedOut.new(@server.address, connection.id),
|
308
|
+
)
|
309
|
+
connection
|
310
|
+
end
|
311
|
+
|
312
|
+
# Check a connection back into the pool.
|
313
|
+
#
|
314
|
+
# The connection must have been previously created by this pool.
|
315
|
+
#
|
316
|
+
# @param [ Mongo::Server::Connection ] connection The connection.
|
317
|
+
#
|
318
|
+
# @since 2.9.0
|
319
|
+
def check_in(connection)
|
320
|
+
@lock.synchronize do
|
321
|
+
unless @checked_out_connections.include?(connection)
|
322
|
+
raise ArgumentError, "Trying to check in a connection which is not currently checked out by this pool: #{connection}"
|
323
|
+
end
|
324
|
+
|
325
|
+
@checked_out_connections.delete(connection)
|
326
|
+
|
327
|
+
# Note: if an event handler raises, resource will not be signaled.
|
328
|
+
# This means threads waiting for a connection to free up when
|
329
|
+
# the pool is at max size may time out.
|
330
|
+
# Threads that begin waiting after this method completes (with
|
331
|
+
# the exception) should be fine.
|
332
|
+
publish_cmap_event(
|
333
|
+
Monitoring::Event::Cmap::ConnectionCheckedIn.new(@server.address, connection.id)
|
334
|
+
)
|
335
|
+
|
336
|
+
if closed?
|
337
|
+
connection.disconnect!(reason: :pool_closed)
|
338
|
+
return
|
339
|
+
end
|
340
|
+
|
341
|
+
if connection.closed?
|
342
|
+
# Connection was closed - for example, because it experienced
|
343
|
+
# a network error. Nothing else needs to be done here.
|
344
|
+
elsif connection.generation != @generation
|
345
|
+
connection.disconnect!(reason: :stale)
|
346
|
+
else
|
347
|
+
connection.record_checkin!
|
348
|
+
@available_connections << connection
|
349
|
+
|
350
|
+
# Wake up only one thread waiting for an available connection,
|
351
|
+
# since only one connection was checked in.
|
352
|
+
@available_semaphore.signal
|
353
|
+
end
|
354
|
+
end
|
82
355
|
end
|
83
356
|
|
84
357
|
# Closes all idle connections in the pool and schedules currently checked
|
@@ -86,14 +359,75 @@ module Mongo
|
|
86
359
|
# The pool remains operational and can create new connections when
|
87
360
|
# requested.
|
88
361
|
#
|
89
|
-
# @
|
90
|
-
#
|
362
|
+
# @option options [ true | false ] :lazy If true, do not close any of
|
363
|
+
# the idle connections and instead let them be closed during a
|
364
|
+
# subsequent check out operation.
|
91
365
|
#
|
92
366
|
# @return [ true ] true.
|
93
367
|
#
|
94
368
|
# @since 2.1.0
|
95
|
-
def
|
96
|
-
|
369
|
+
def clear(options = nil)
|
370
|
+
raise_if_closed!
|
371
|
+
|
372
|
+
@lock.synchronize do
|
373
|
+
@generation += 1
|
374
|
+
|
375
|
+
publish_cmap_event(
|
376
|
+
Monitoring::Event::Cmap::PoolCleared.new(@server.address)
|
377
|
+
)
|
378
|
+
|
379
|
+
unless options && options[:lazy]
|
380
|
+
until @available_connections.empty?
|
381
|
+
connection = @available_connections.pop
|
382
|
+
connection.disconnect!(reason: :stale)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
true
|
388
|
+
end
|
389
|
+
|
390
|
+
# @since 2.1.0
|
391
|
+
# @deprecated
|
392
|
+
alias :disconnect! :clear
|
393
|
+
|
394
|
+
# Marks the pool closed, closes all idle connections in the pool and
|
395
|
+
# schedules currently checked out connections to be closed when they are
|
396
|
+
# checked back into the pool. If force option is true, checked out
|
397
|
+
# connections are also closed. Attempts to use the pool after it is closed
|
398
|
+
# will raise Error::PoolClosedError.
|
399
|
+
#
|
400
|
+
# @option options [ true | false ] :force Also close all checked out
|
401
|
+
# connections.
|
402
|
+
#
|
403
|
+
# @return [ true ] true.
|
404
|
+
#
|
405
|
+
# @since 2.9.0
|
406
|
+
def close(options = nil)
|
407
|
+
return if closed?
|
408
|
+
|
409
|
+
@lock.synchronize do
|
410
|
+
until @available_connections.empty?
|
411
|
+
connection = @available_connections.pop
|
412
|
+
connection.disconnect!(reason: :pool_closed)
|
413
|
+
end
|
414
|
+
|
415
|
+
if options && options[:force]
|
416
|
+
until @checked_out_connections.empty?
|
417
|
+
connection = @checked_out_connections.take(1).first
|
418
|
+
connection.disconnect!(reason: :pool_closed)
|
419
|
+
@checked_out_connections.delete(connection)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
@closed = true
|
425
|
+
|
426
|
+
publish_cmap_event(
|
427
|
+
Monitoring::Event::Cmap::PoolClosed.new(@server.address)
|
428
|
+
)
|
429
|
+
|
430
|
+
true
|
97
431
|
end
|
98
432
|
|
99
433
|
# Get a pretty printed string inspection for the pool.
|
@@ -105,10 +439,16 @@ module Mongo
|
|
105
439
|
#
|
106
440
|
# @since 2.0.0
|
107
441
|
def inspect
|
108
|
-
|
442
|
+
if closed?
|
443
|
+
"#<Mongo::Server::ConnectionPool:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
|
444
|
+
"wait_timeout=#{wait_timeout} closed>"
|
445
|
+
else
|
446
|
+
"#<Mongo::Server::ConnectionPool:0x#{object_id} min_size=#{min_size} max_size=#{max_size} " +
|
447
|
+
"wait_timeout=#{wait_timeout} current_size=#{size} available=#{available_count}>"
|
448
|
+
end
|
109
449
|
end
|
110
450
|
|
111
|
-
# Yield the block to a connection, while handling
|
451
|
+
# Yield the block to a connection, while handling check in/check out logic.
|
112
452
|
#
|
113
453
|
# @example Execute with a connection.
|
114
454
|
# pool.with_connection do |connection|
|
@@ -119,15 +459,71 @@ module Mongo
|
|
119
459
|
#
|
120
460
|
# @since 2.0.0
|
121
461
|
def with_connection
|
122
|
-
|
462
|
+
raise_if_closed!
|
463
|
+
|
464
|
+
connection = check_out
|
123
465
|
yield(connection)
|
124
466
|
ensure
|
125
|
-
|
467
|
+
if connection
|
468
|
+
check_in(connection)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
# Close sockets that have been open for longer than the max idle time,
|
473
|
+
# if the option is set.
|
474
|
+
#
|
475
|
+
# @since 2.5.0
|
476
|
+
def close_idle_sockets
|
477
|
+
return if closed?
|
478
|
+
return unless max_idle_time
|
479
|
+
|
480
|
+
@lock.synchronize do
|
481
|
+
i = 0
|
482
|
+
while i < @available_connections.length
|
483
|
+
connection = @available_connections[i]
|
484
|
+
if last_checkin = connection.last_checkin
|
485
|
+
if (Time.now - last_checkin) > max_idle_time
|
486
|
+
connection.disconnect!(reason: :idle)
|
487
|
+
@available_connections.delete_at(i)
|
488
|
+
next
|
489
|
+
end
|
490
|
+
end
|
491
|
+
i += 1
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
# Creates up to the min size connections.
|
497
|
+
#
|
498
|
+
# Used by the spec test runner.
|
499
|
+
#
|
500
|
+
# @api private
|
501
|
+
def populate
|
502
|
+
while size < min_size
|
503
|
+
@available_connections << create_connection
|
504
|
+
end
|
126
505
|
end
|
127
506
|
|
128
|
-
|
507
|
+
private
|
508
|
+
|
509
|
+
def create_connection
|
510
|
+
connection = Connection.new(@server, options.merge(generation: generation))
|
511
|
+
# CMAP spec requires connections to be returned from the pool
|
512
|
+
# fully established.
|
513
|
+
#connection.connect!
|
514
|
+
connection
|
515
|
+
end
|
129
516
|
|
130
|
-
|
517
|
+
# Asserts that the pool has not been closed.
|
518
|
+
#
|
519
|
+
# @raise [ Error::PoolClosedError ] If the pool has been closed.
|
520
|
+
#
|
521
|
+
# @since 2.9.0
|
522
|
+
def raise_if_closed!
|
523
|
+
if closed?
|
524
|
+
raise Error::PoolClosedError.new(@server.address)
|
525
|
+
end
|
526
|
+
end
|
131
527
|
end
|
132
528
|
end
|
133
529
|
end
|