mongo 2.5.0.beta → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongo/address.rb +1 -1
- data/lib/mongo/address/unix.rb +1 -1
- data/lib/mongo/auth/user.rb +0 -5
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/bulk_write.rb +60 -32
- data/lib/mongo/client.rb +44 -8
- data/lib/mongo/cluster.rb +14 -12
- data/lib/mongo/cluster/periodic_executor.rb +106 -0
- data/lib/mongo/cluster/{cursor_reaper.rb → reapers/cursor_reaper.rb} +5 -37
- data/lib/mongo/cluster/reapers/socket_reaper.rb +59 -0
- data/lib/mongo/collection.rb +9 -6
- data/lib/mongo/collection/view.rb +2 -2
- data/lib/mongo/collection/view/builder/aggregation.rb +2 -1
- data/lib/mongo/collection/view/builder/find_command.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +14 -1
- data/lib/mongo/collection/view/map_reduce.rb +30 -13
- data/lib/mongo/collection/view/readable.rb +5 -5
- data/lib/mongo/collection/view/writable.rb +98 -51
- data/lib/mongo/error.rb +3 -0
- data/lib/mongo/error/invalid_txt_record.rb +27 -0
- data/lib/mongo/error/invalid_uri.rb +7 -6
- data/lib/mongo/error/mismatched_domain.rb +27 -0
- data/lib/mongo/error/no_srv_records.rb +26 -0
- data/lib/mongo/error/unsupported_features.rb +0 -18
- data/lib/mongo/index/view.rb +2 -2
- data/lib/mongo/operation.rb +1 -0
- data/lib/mongo/operation/causally_consistent.rb +33 -0
- data/lib/mongo/operation/commands.rb +2 -1
- data/lib/mongo/operation/commands/aggregate.rb +2 -7
- data/lib/mongo/operation/commands/count.rb +27 -0
- data/lib/mongo/operation/commands/distinct.rb +27 -0
- data/lib/mongo/operation/commands/find.rb +3 -1
- data/lib/mongo/operation/commands/map_reduce.rb +1 -0
- data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
- data/lib/mongo/operation/specifiable.rb +12 -0
- data/lib/mongo/operation/uses_command_op_msg.rb +36 -5
- data/lib/mongo/operation/write.rb +0 -5
- data/lib/mongo/operation/write/bulk/bulkable.rb +4 -8
- data/lib/mongo/operation/write/bulk/mergable.rb +2 -0
- data/lib/mongo/operation/write/command/create_index.rb +19 -0
- data/lib/mongo/operation/write/command/create_user.rb +19 -0
- data/lib/mongo/operation/write/command/delete.rb +1 -2
- data/lib/mongo/operation/write/command/drop_index.rb +19 -0
- data/lib/mongo/operation/write/command/insert.rb +1 -2
- data/lib/mongo/operation/write/command/remove_user.rb +19 -0
- data/lib/mongo/operation/write/command/update.rb +1 -2
- data/lib/mongo/operation/write/command/update_user.rb +19 -0
- data/lib/mongo/operation/write/write_command_enabled.rb +1 -3
- data/lib/mongo/protocol/compressed.rb +2 -1
- data/lib/mongo/protocol/serializers.rb +6 -6
- data/lib/mongo/retryable.rb +48 -5
- data/lib/mongo/server.rb +15 -0
- data/lib/mongo/server/connection.rb +21 -1
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/connection_pool/queue.rb +50 -5
- data/lib/mongo/server/description.rb +11 -3
- data/lib/mongo/server/description/features.rb +26 -7
- data/lib/mongo/session.rb +133 -6
- data/lib/mongo/session/server_session.rb +30 -0
- data/lib/mongo/session/session_pool.rb +20 -20
- data/lib/mongo/uri.rb +88 -44
- data/lib/mongo/uri/srv_protocol.rb +158 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern/normalizable.rb +12 -0
- data/mongo.gemspec +1 -2
- data/spec/mongo/address_spec.rb +12 -0
- data/spec/mongo/auth/user/view_spec.rb +1 -5
- data/spec/mongo/bulk_write_spec.rb +232 -401
- data/spec/mongo/change_stream_examples_spec.rb +150 -0
- data/spec/mongo/client_spec.rb +142 -2
- data/spec/mongo/cluster/cursor_reaper_spec.rb +0 -70
- data/spec/mongo/cluster/socket_reaper_spec.rb +32 -0
- data/spec/mongo/cluster_spec.rb +11 -7
- data/spec/mongo/collection/view/aggregation_spec.rb +46 -1
- data/spec/mongo/collection/view/builder/find_command_spec.rb +15 -0
- data/spec/mongo/collection/view/change_stream_spec.rb +79 -12
- data/spec/mongo/collection/view/map_reduce_spec.rb +120 -4
- data/spec/mongo/collection/view/readable_spec.rb +23 -5
- data/spec/mongo/collection_spec.rb +292 -102
- data/spec/mongo/command_monitoring_spec.rb +26 -32
- data/spec/mongo/crud_spec.rb +1 -1
- data/spec/mongo/cursor_spec.rb +2 -3
- data/spec/mongo/database_spec.rb +30 -14
- data/spec/mongo/dns_seedlist_discovery_spec.rb +94 -0
- data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
- data/spec/mongo/grid/stream/write_spec.rb +1 -1
- data/spec/mongo/index/view_spec.rb +8 -46
- data/spec/mongo/operation/write/bulk/delete_spec.rb +2 -2
- data/spec/mongo/operation/write/bulk/insert_spec.rb +2 -10
- data/spec/mongo/operation/write/{create_index_spec.rb → command/create_index_spec.rb} +2 -6
- data/spec/mongo/operation/write/command/delete_spec.rb +35 -7
- data/spec/mongo/operation/write/{drop_index_spec.rb → command/drop_index_spec.rb} +1 -1
- data/spec/mongo/operation/write/command/insert_spec.rb +37 -6
- data/spec/mongo/operation/write/{remove_user_spec.rb → command/remove_user_spec.rb} +2 -6
- data/spec/mongo/operation/write/command/update_spec.rb +34 -7
- data/spec/mongo/operation/write/{update_user_spec.rb → command/update_user_spec.rb} +1 -1
- data/spec/mongo/operation/write/create_user_spec.rb +1 -1
- data/spec/mongo/operation/write/delete_spec.rb +1 -1
- data/spec/mongo/operation/write/insert_spec.rb +2 -10
- data/spec/mongo/operation/write/update_spec.rb +3 -15
- data/spec/mongo/retryable_spec.rb +1 -1
- data/spec/mongo/retryable_writes_spec.rb +815 -0
- data/spec/mongo/server/connection_pool/queue_spec.rb +35 -2
- data/spec/mongo/server/connection_pool_spec.rb +234 -1
- data/spec/mongo/server/connection_spec.rb +10 -6
- data/spec/mongo/server/description/features_spec.rb +51 -37
- data/spec/mongo/server/description_spec.rb +6 -3
- data/spec/mongo/server_spec.rb +87 -0
- data/spec/mongo/session/server_session_spec.rb +43 -0
- data/spec/mongo/session/session_pool_spec.rb +63 -27
- data/spec/mongo/session_spec.rb +247 -0
- data/spec/mongo/shell_examples_spec.rb +2 -2
- data/spec/mongo/uri/srv_protocol_spec.rb +933 -0
- data/spec/mongo/uri_spec.rb +42 -3
- data/spec/mongo/write_concern/acknowledged_spec.rb +11 -0
- data/spec/mongo/write_concern/unacknowledged_spec.rb +11 -0
- data/spec/spec_helper.rb +11 -25
- data/spec/support/authorization.rb +2 -1
- data/spec/support/connection_string.rb +8 -4
- data/spec/support/crud.rb +38 -24
- data/spec/support/crud/write.rb +30 -3
- data/spec/support/crud_tests/read/aggregate-out.yml +21 -0
- data/spec/support/crud_tests/write/bulkWrite-arrayFilters.yml +44 -0
- data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +1 -1
- data/spec/support/crud_tests/write/insertMany.yml +1 -3
- data/spec/support/crud_tests/write/replaceOne.yml +1 -1
- data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +1 -1
- data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +1 -1
- data/spec/support/dns_seedlist_discovery_tests/longer-parent-in-return.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/misformatted-option.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/no-results.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/not-enough-parts.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/one-result-default-port.yml +10 -0
- data/spec/support/dns_seedlist_discovery_tests/one-txt-record-multiple-strings.yml +10 -0
- data/spec/support/dns_seedlist_discovery_tests/one-txt-record.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch1.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch2.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch3.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch4.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch5.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/returned-parent-too-short.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/returned-parent-wrong.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/two-results-default-port.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/two-results-nonstandard-port.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/two-txt-records.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-not-allowed-option.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-ssl-option.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-uri-option.yml +11 -0
- data/spec/support/dns_seedlist_discovery_tests/txt-record-with-unallowed-option.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/uri-with-port.yml +5 -0
- data/spec/support/dns_seedlist_discovery_tests/uri-with-two-hosts.yml +5 -0
- data/spec/support/retryable_writes_tests/bulkWrite.yml +305 -0
- data/spec/support/retryable_writes_tests/deleteOne.yml +51 -0
- data/spec/support/retryable_writes_tests/findOneAndDelete.yml +52 -0
- data/spec/support/retryable_writes_tests/findOneAndReplace.yml +57 -0
- data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +56 -0
- data/spec/support/retryable_writes_tests/insertMany.yml +72 -0
- data/spec/support/retryable_writes_tests/insertOne.yml +55 -0
- data/spec/support/retryable_writes_tests/replaceOne.yml +60 -0
- data/spec/support/retryable_writes_tests/updateOne.yml +120 -0
- data/spec/support/shared/session.rb +525 -24
- metadata +437 -350
- metadata.gz.sig +0 -0
- data/lib/mongo/operation/commands/user_query.rb +0 -72
- data/lib/mongo/operation/write/create_index.rb +0 -67
- data/lib/mongo/operation/write/create_user.rb +0 -50
- data/lib/mongo/operation/write/drop_index.rb +0 -63
- data/lib/mongo/operation/write/remove_user.rb +0 -48
- data/lib/mongo/operation/write/update_user.rb +0 -50
@@ -34,6 +34,7 @@ module Mongo
|
|
34
34
|
#
|
35
35
|
# @since 2.0.0
|
36
36
|
def aggregate_write_errors(count)
|
37
|
+
return unless @replies
|
37
38
|
@replies.reduce(nil) do |errors, reply|
|
38
39
|
if write_errors = reply.documents.first[Error::WRITE_ERRORS]
|
39
40
|
wes = write_errors.collect do |we|
|
@@ -55,6 +56,7 @@ module Mongo
|
|
55
56
|
#
|
56
57
|
# @since 2.0.0
|
57
58
|
def aggregate_write_concern_errors(count)
|
59
|
+
return unless @replies
|
58
60
|
@replies.each_with_index.reduce(nil) do |errors, (reply, _)|
|
59
61
|
if write_concern_errors = reply.documents.first[Error::WRITE_CONCERN_ERRORS]
|
60
62
|
(errors || []) << write_concern_errors.reduce(nil) do |errs, wce|
|
@@ -33,6 +33,25 @@ module Mongo
|
|
33
33
|
include TakesWriteConcern
|
34
34
|
include UsesCommandOpMsg
|
35
35
|
|
36
|
+
# Execute the operation.
|
37
|
+
#
|
38
|
+
# @example Execute the operation.
|
39
|
+
# operation.execute(server)
|
40
|
+
#
|
41
|
+
# @param [ Mongo::Server ] server The server to send this operation to.
|
42
|
+
#
|
43
|
+
# @return [ Result ] The operation response, if there is one.
|
44
|
+
#
|
45
|
+
# @since 2.5.0
|
46
|
+
def execute(server)
|
47
|
+
result = Result.new(server.with_connection do |connection|
|
48
|
+
connection.dispatch([ message(server) ], operation_id)
|
49
|
+
end)
|
50
|
+
server.update_cluster_time(result)
|
51
|
+
session.process(result) if session
|
52
|
+
result.validate!
|
53
|
+
end
|
54
|
+
|
36
55
|
private
|
37
56
|
|
38
57
|
# The query selector for this ensure index command operation.
|
@@ -25,6 +25,25 @@ module Mongo
|
|
25
25
|
include Specifiable
|
26
26
|
include Writable
|
27
27
|
|
28
|
+
# Execute the operation.
|
29
|
+
#
|
30
|
+
# @example Execute the operation.
|
31
|
+
# operation.execute(server)
|
32
|
+
#
|
33
|
+
# @param [ Mongo::Server ] server The server to send this operation to.
|
34
|
+
#
|
35
|
+
# @return [ Result ] The operation response, if there is one.
|
36
|
+
#
|
37
|
+
# @since 2.5.0
|
38
|
+
def execute(server)
|
39
|
+
result = Result.new(server.with_connection do |connection|
|
40
|
+
connection.dispatch([ message(server) ], operation_id)
|
41
|
+
end)
|
42
|
+
server.update_cluster_time(result)
|
43
|
+
session.process(result) if session
|
44
|
+
result.validate!
|
45
|
+
end
|
46
|
+
|
28
47
|
private
|
29
48
|
|
30
49
|
# The query selector for this create user command operation.
|
@@ -52,8 +52,7 @@ module Mongo
|
|
52
52
|
global_args = { delete: coll_name,
|
53
53
|
Protocol::Msg::DATABASE_IDENTIFIER => db_name
|
54
54
|
}.merge!(command_options)
|
55
|
-
|
56
|
-
session.add_id!(global_args) if session
|
55
|
+
update_selector_for_session!(global_args, server)
|
57
56
|
|
58
57
|
section = { type: 1, payload: { identifier: IDENTIFIER, sequence: deletes } }
|
59
58
|
flags = unacknowledged_write? ? [:more_to_come] : [:none]
|
@@ -34,6 +34,25 @@ module Mongo
|
|
34
34
|
include TakesWriteConcern
|
35
35
|
include UsesCommandOpMsg
|
36
36
|
|
37
|
+
# Execute the operation.
|
38
|
+
#
|
39
|
+
# @example Execute the operation.
|
40
|
+
# operation.execute(server)
|
41
|
+
#
|
42
|
+
# @param [ Mongo::Server ] server The server to send this operation to.
|
43
|
+
#
|
44
|
+
# @return [ Result ] The operation response, if there is one.
|
45
|
+
#
|
46
|
+
# @since 2.5.0
|
47
|
+
def execute(server)
|
48
|
+
result = Result.new(server.with_connection do |connection|
|
49
|
+
connection.dispatch([ message(server) ], operation_id)
|
50
|
+
end)
|
51
|
+
server.update_cluster_time(result)
|
52
|
+
session.process(result) if session
|
53
|
+
result.validate!
|
54
|
+
end
|
55
|
+
|
37
56
|
private
|
38
57
|
|
39
58
|
# The query selector for this drop index command operation.
|
@@ -46,8 +46,7 @@ module Mongo
|
|
46
46
|
global_args = { insert: coll_name,
|
47
47
|
Protocol::Msg::DATABASE_IDENTIFIER => db_name
|
48
48
|
}.merge!(command_options)
|
49
|
-
|
50
|
-
session.add_id!(global_args) if session
|
49
|
+
update_selector_for_session!(global_args, server)
|
51
50
|
|
52
51
|
section = { type: 1, payload: { identifier: IDENTIFIER, sequence: documents } }
|
53
52
|
flags = unacknowledged_write? ? [:more_to_come] : [:none]
|
@@ -24,6 +24,25 @@ module Mongo
|
|
24
24
|
include Specifiable
|
25
25
|
include Writable
|
26
26
|
|
27
|
+
# Execute the operation.
|
28
|
+
#
|
29
|
+
# @example Execute the operation.
|
30
|
+
# operation.execute(server)
|
31
|
+
#
|
32
|
+
# @param [ Mongo::Server ] server The server to send this operation to.
|
33
|
+
#
|
34
|
+
# @return [ Result ] The operation response, if there is one.
|
35
|
+
#
|
36
|
+
# @since 2.5.0
|
37
|
+
def execute(server)
|
38
|
+
result = Result.new(server.with_connection do |connection|
|
39
|
+
connection.dispatch([ message(server) ], operation_id)
|
40
|
+
end)
|
41
|
+
server.update_cluster_time(result)
|
42
|
+
session.process(result) if session
|
43
|
+
result.validate!
|
44
|
+
end
|
45
|
+
|
27
46
|
private
|
28
47
|
|
29
48
|
# The query selector for this drop user command operation.
|
@@ -55,8 +55,7 @@ module Mongo
|
|
55
55
|
global_args = { update: coll_name,
|
56
56
|
Protocol::Msg::DATABASE_IDENTIFIER => db_name
|
57
57
|
}.merge!(command_options)
|
58
|
-
|
59
|
-
session.add_id!(global_args) if session
|
58
|
+
update_selector_for_session!(global_args, server)
|
60
59
|
|
61
60
|
section = { type: 1, payload: { identifier: IDENTIFIER, sequence: updates } }
|
62
61
|
flags = unacknowledged_write? ? [:more_to_come] : [:none]
|
@@ -25,6 +25,25 @@ module Mongo
|
|
25
25
|
include Specifiable
|
26
26
|
include Writable
|
27
27
|
|
28
|
+
# Execute the operation.
|
29
|
+
#
|
30
|
+
# @example Execute the operation.
|
31
|
+
# operation.execute(server)
|
32
|
+
#
|
33
|
+
# @param [ Mongo::Server ] server The server to send this operation to.
|
34
|
+
#
|
35
|
+
# @return [ Result ] The operation response, if there is one.
|
36
|
+
#
|
37
|
+
# @since 2.5.0
|
38
|
+
def execute(server)
|
39
|
+
result = Result.new(server.with_connection do |connection|
|
40
|
+
connection.dispatch([ message(server) ], operation_id)
|
41
|
+
end)
|
42
|
+
server.update_cluster_time(result)
|
43
|
+
session.process(result) if session
|
44
|
+
result.validate!
|
45
|
+
end
|
46
|
+
|
28
47
|
private
|
29
48
|
|
30
49
|
# The query selector for this update user command operation.
|
@@ -39,9 +39,7 @@ module Mongo
|
|
39
39
|
raise Error::UnsupportedArrayFilters.new(Error::UnsupportedArrayFilters::UNACKNOWLEDGED_WRITES_MESSAGE) if has_array_filters?
|
40
40
|
end
|
41
41
|
|
42
|
-
if
|
43
|
-
execute_message(server)
|
44
|
-
elsif server.features.op_msg_enabled? # version 3.6
|
42
|
+
if server.features.op_msg_enabled? # version 3.6
|
45
43
|
execute_write_command(server)
|
46
44
|
else # server version is 2.6 through 3.4
|
47
45
|
if unacknowledged_write?
|
@@ -48,7 +48,8 @@ module Mongo
|
|
48
48
|
#
|
49
49
|
# @param [ Mongo::Protocol::Message ] message The original message.
|
50
50
|
# @param [ String, Symbol ] compressor The compression algorithm to use.
|
51
|
-
# @param [ Integer ]
|
51
|
+
# @param [ Integer ] zlib_compression_level The zlib compression level to use.
|
52
|
+
# -1 and nil imply default.
|
52
53
|
#
|
53
54
|
# @since 2.5.0
|
54
55
|
def initialize(message, compressor, zlib_compression_level = nil)
|
@@ -355,9 +355,9 @@ module Mongo
|
|
355
355
|
|
356
356
|
# Writes a byte into the buffer.
|
357
357
|
#
|
358
|
-
# @param
|
359
|
-
# @param
|
360
|
-
# @param
|
358
|
+
# @param [ BSON::ByteBuffer ] buffer Buffer to receive the single byte.
|
359
|
+
# @param [ String ] value The byte to write to the buffer.
|
360
|
+
# @param [ true, false ] validating_keys Whether to validate keys.
|
361
361
|
#
|
362
362
|
# @return [ BSON::ByteBuffer ] Buffer with serialized value.
|
363
363
|
#
|
@@ -385,9 +385,9 @@ module Mongo
|
|
385
385
|
|
386
386
|
# Writes bytes into the buffer.
|
387
387
|
#
|
388
|
-
# @param
|
389
|
-
# @param
|
390
|
-
# @param
|
388
|
+
# @param [ BSON::ByteBuffer ] buffer Buffer to receive the bytes.
|
389
|
+
# @param [ String ] value The bytes to write to the buffer.
|
390
|
+
# @param [ true, false ] validating_keys Whether to validate keys.
|
391
391
|
#
|
392
392
|
# @return [ BSON::ByteBuffer ] Buffer with serialized value.
|
393
393
|
#
|
data/lib/mongo/retryable.rb
CHANGED
@@ -30,7 +30,6 @@ module Mongo
|
|
30
30
|
#
|
31
31
|
# @note This only retries read operations on socket errors.
|
32
32
|
#
|
33
|
-
# @param [ Integer ] attempt The retry attempt count - for internal use.
|
34
33
|
# @param [ Proc ] block The block to execute.
|
35
34
|
#
|
36
35
|
# @yieldparam [ Server ] server The server to which the write should be sent.
|
@@ -99,12 +98,58 @@ module Mongo
|
|
99
98
|
# @return [ Result ] The result of the operation.
|
100
99
|
#
|
101
100
|
# @since 2.1.0
|
102
|
-
def write_with_retry(session,
|
101
|
+
def write_with_retry(session, write_concern, &block)
|
102
|
+
unless retry_write_allowed?(session, write_concern)
|
103
|
+
return legacy_write_with_retry(&block)
|
104
|
+
end
|
105
|
+
|
106
|
+
server = cluster.next_primary
|
107
|
+
unless server.retry_writes?
|
108
|
+
return legacy_write_with_retry(server, &block)
|
109
|
+
end
|
110
|
+
|
111
|
+
begin
|
112
|
+
txn_num = session.next_txn_num
|
113
|
+
yield(server, txn_num)
|
114
|
+
rescue Error::SocketError, Error::SocketTimeoutError => e
|
115
|
+
retry_write(e, txn_num, &block)
|
116
|
+
rescue Error::OperationFailure => e
|
117
|
+
raise e unless e.write_retryable?
|
118
|
+
retry_write(e, txn_num, &block)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def retry_write_allowed?(session, write_concern)
|
125
|
+
session && session.retry_writes? &&
|
126
|
+
(write_concern.nil? || write_concern.acknowledged?)
|
127
|
+
end
|
128
|
+
|
129
|
+
def retry_write(original_error, txn_num, &block)
|
130
|
+
cluster.scan!
|
131
|
+
server = cluster.next_primary
|
132
|
+
raise original_error unless (server.retry_writes? && txn_num)
|
133
|
+
log_retry(original_error)
|
134
|
+
yield(server, txn_num)
|
135
|
+
rescue Error::SocketError, Error::SocketTimeoutError => e
|
136
|
+
cluster.scan!
|
137
|
+
raise e
|
138
|
+
rescue Error::OperationFailure => e
|
139
|
+
raise original_error unless e.write_retryable?
|
140
|
+
cluster.scan!
|
141
|
+
raise e
|
142
|
+
rescue
|
143
|
+
raise original_error
|
144
|
+
end
|
145
|
+
|
146
|
+
def legacy_write_with_retry(server = nil)
|
103
147
|
attempt = 0
|
104
148
|
begin
|
105
149
|
attempt += 1
|
106
|
-
yield(
|
150
|
+
yield(server || cluster.next_primary)
|
107
151
|
rescue Error::OperationFailure => e
|
152
|
+
server = nil
|
108
153
|
raise(e) if attempt > Cluster::MAX_WRITE_RETRIES
|
109
154
|
if e.write_retryable?
|
110
155
|
log_retry(e)
|
@@ -116,8 +161,6 @@ module Mongo
|
|
116
161
|
end
|
117
162
|
end
|
118
163
|
|
119
|
-
private
|
120
|
-
|
121
164
|
# Log a warning so that any application slow down is immediately obvious.
|
122
165
|
def log_retry(e)
|
123
166
|
Logger.logger.warn "Retry due to: #{e.class.name} #{e.message}"
|
data/lib/mongo/server.rb
CHANGED
@@ -268,5 +268,20 @@ module Mongo
|
|
268
268
|
unknown!
|
269
269
|
raise
|
270
270
|
end
|
271
|
+
|
272
|
+
# Will writes sent to this server be retried.
|
273
|
+
#
|
274
|
+
# @example Will writes be retried.
|
275
|
+
# server.retry_writes?
|
276
|
+
#
|
277
|
+
# @return [ true, false ] If writes will be retried.
|
278
|
+
#
|
279
|
+
# @note Retryable writes are only available on server versions 3.6+ and with
|
280
|
+
# sharded clusters or replica sets.
|
281
|
+
#
|
282
|
+
# @since 2.5.0
|
283
|
+
def retry_writes?
|
284
|
+
!!(features.sessions_enabled? && logical_session_timeout && !standalone?)
|
285
|
+
end
|
271
286
|
end
|
272
287
|
end
|
@@ -54,6 +54,11 @@ module Mongo
|
|
54
54
|
# @since 2.5.0
|
55
55
|
PING_OP_MSG_BYTES = PING_OP_MSG_MESSAGE.serialize.to_s.freeze
|
56
56
|
|
57
|
+
# The last time the connection was checked back into a pool.
|
58
|
+
#
|
59
|
+
# @since 2.5.0
|
60
|
+
attr_reader :last_checkin
|
61
|
+
|
57
62
|
def_delegators :@server,
|
58
63
|
:features,
|
59
64
|
:max_bson_object_size,
|
@@ -97,9 +102,10 @@ module Mongo
|
|
97
102
|
#
|
98
103
|
# @since 2.0.0
|
99
104
|
def disconnect!
|
105
|
+
@auth_mechanism = nil
|
106
|
+
@last_checkin = nil
|
100
107
|
if socket
|
101
108
|
socket.close
|
102
|
-
@auth_mechanism = nil
|
103
109
|
@socket = nil
|
104
110
|
end
|
105
111
|
true
|
@@ -151,6 +157,7 @@ module Mongo
|
|
151
157
|
@server = server
|
152
158
|
@ssl_options = options.reject { |k, v| !k.to_s.start_with?(SSL) }
|
153
159
|
@socket = nil
|
160
|
+
@last_checkin = nil
|
154
161
|
@auth_mechanism = nil
|
155
162
|
@pid = Process.pid
|
156
163
|
end
|
@@ -189,6 +196,19 @@ module Mongo
|
|
189
196
|
# @deprecated Please use :socket_timeout instead. Will be removed in 3.0.0
|
190
197
|
alias :timeout :socket_timeout
|
191
198
|
|
199
|
+
# Record the last checkin time.
|
200
|
+
#
|
201
|
+
# @example Record the checkin time on this connection.
|
202
|
+
# connection.record_checkin!
|
203
|
+
#
|
204
|
+
# @return [ self ]
|
205
|
+
#
|
206
|
+
# @since 2.5.0
|
207
|
+
def record_checkin!
|
208
|
+
@last_checkin = Time.now
|
209
|
+
self
|
210
|
+
end
|
211
|
+
|
192
212
|
private
|
193
213
|
|
194
214
|
def deliver(messages)
|
@@ -22,10 +22,13 @@ module Mongo
|
|
22
22
|
# @since 2.0.0
|
23
23
|
class ConnectionPool
|
24
24
|
include Loggable
|
25
|
+
extend Forwardable
|
25
26
|
|
26
27
|
# @return [ Hash ] options The pool options.
|
27
28
|
attr_reader :options
|
28
29
|
|
30
|
+
def_delegators :queue, :close_stale_sockets!
|
31
|
+
|
29
32
|
# Check a connection back into the pool. Will pull the connection from a
|
30
33
|
# thread local stack that should contain it after it was checked out.
|
31
34
|
#
|
@@ -16,9 +16,8 @@ module Mongo
|
|
16
16
|
class Server
|
17
17
|
class ConnectionPool
|
18
18
|
|
19
|
-
# A
|
20
|
-
# based on mperham's connection pool
|
21
|
-
# stack.
|
19
|
+
# A LIFO queue of connections to be used by the connection pool. This is
|
20
|
+
# based on mperham's connection pool.
|
22
21
|
#
|
23
22
|
# @since 2.0.0
|
24
23
|
class Queue
|
@@ -88,7 +87,7 @@ module Mongo
|
|
88
87
|
# @since 2.0.0
|
89
88
|
def enqueue(connection)
|
90
89
|
mutex.synchronize do
|
91
|
-
queue.unshift(connection)
|
90
|
+
queue.unshift(connection.record_checkin!)
|
92
91
|
resource.broadcast
|
93
92
|
end
|
94
93
|
end
|
@@ -165,12 +164,58 @@ module Mongo
|
|
165
164
|
@wait_timeout ||= options[:wait_queue_timeout] || WAIT_TIMEOUT
|
166
165
|
end
|
167
166
|
|
167
|
+
# The maximum seconds a socket can remain idle since it has been checked in to the pool.
|
168
|
+
#
|
169
|
+
# @example Get the max idle time.
|
170
|
+
# queue.max_idle_time
|
171
|
+
#
|
172
|
+
# @return [ Float ] The max socket idle time in seconds.
|
173
|
+
#
|
174
|
+
# @since 2.5.0
|
175
|
+
def max_idle_time
|
176
|
+
@max_idle_time ||= options[:max_idle_time]
|
177
|
+
end
|
178
|
+
|
179
|
+
# Close sockets that have been open for longer than the max idle time, if the
|
180
|
+
# option is set.
|
181
|
+
#
|
182
|
+
# @example Close the stale sockets
|
183
|
+
# queue.close_stale_sockets!
|
184
|
+
#
|
185
|
+
# @since 2.5.0
|
186
|
+
def close_stale_sockets!
|
187
|
+
return unless max_idle_time
|
188
|
+
|
189
|
+
to_refresh = []
|
190
|
+
queue.each do |connection|
|
191
|
+
if last_checkin = connection.last_checkin
|
192
|
+
if (Time.now - last_checkin) > max_idle_time
|
193
|
+
to_refresh << connection
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
mutex.synchronize do
|
199
|
+
num_checked_out = @connections - queue.size
|
200
|
+
min_size_delta = [(min_size - num_checked_out), 0].max
|
201
|
+
|
202
|
+
to_refresh.each do |connection|
|
203
|
+
if queue.include?(connection)
|
204
|
+
connection.disconnect!
|
205
|
+
if queue.index(connection) < min_size_delta
|
206
|
+
begin; connection.connect!; rescue; end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
168
213
|
private
|
169
214
|
|
170
215
|
def dequeue_connection
|
171
216
|
deadline = Time.now + wait_timeout
|
172
217
|
loop do
|
173
|
-
return queue.
|
218
|
+
return queue.shift unless queue.empty?
|
174
219
|
connection = create_connection
|
175
220
|
return connection if connection
|
176
221
|
wait_for_next!(deadline)
|