mongo 2.20.1 → 2.21.0
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
- data/README.md +3 -0
- data/Rakefile +2 -2
- data/lib/mongo/address.rb +22 -3
- data/lib/mongo/auth/aws/credentials_retriever.rb +70 -17
- data/lib/mongo/auth/base.rb +1 -1
- data/lib/mongo/bulk_write.rb +35 -2
- data/lib/mongo/client.rb +38 -6
- data/lib/mongo/client_encryption.rb +6 -3
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +6 -1
- data/lib/mongo/cluster/sdam_flow.rb +20 -7
- data/lib/mongo/cluster.rb +14 -4
- data/lib/mongo/collection/helpers.rb +1 -1
- data/lib/mongo/collection/view/aggregation/behavior.rb +131 -0
- data/lib/mongo/collection/view/aggregation.rb +33 -99
- data/lib/mongo/collection/view/builder/aggregation.rb +1 -7
- data/lib/mongo/collection/view/change_stream.rb +80 -27
- data/lib/mongo/collection/view/iterable.rb +76 -60
- data/lib/mongo/collection/view/map_reduce.rb +25 -8
- data/lib/mongo/collection/view/readable.rb +79 -30
- data/lib/mongo/collection/view/writable.rb +109 -48
- data/lib/mongo/collection/view.rb +43 -3
- data/lib/mongo/collection.rb +158 -23
- data/lib/mongo/crypt/auto_encrypter.rb +4 -6
- data/lib/mongo/crypt/binding.rb +4 -4
- data/lib/mongo/crypt/context.rb +20 -14
- data/lib/mongo/crypt/encryption_io.rb +56 -26
- data/lib/mongo/crypt/explicit_encrypter.rb +49 -20
- data/lib/mongo/crypt/explicit_encryption_context.rb +17 -11
- data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +22 -6
- data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +29 -4
- data/lib/mongo/csot_timeout_holder.rb +119 -0
- data/lib/mongo/cursor/kill_spec.rb +5 -2
- data/lib/mongo/cursor/nontailable.rb +27 -0
- data/lib/mongo/cursor.rb +86 -24
- data/lib/mongo/cursor_host.rb +82 -0
- data/lib/mongo/database/view.rb +81 -14
- data/lib/mongo/database.rb +88 -18
- data/lib/mongo/error/operation_failure.rb +209 -204
- data/lib/mongo/error/server_timeout_error.rb +12 -0
- data/lib/mongo/error/socket_timeout_error.rb +3 -1
- data/lib/mongo/error/timeout_error.rb +23 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +45 -12
- data/lib/mongo/grid/stream/read.rb +15 -1
- data/lib/mongo/grid/stream/write.rb +21 -4
- data/lib/mongo/index/view.rb +77 -16
- data/lib/mongo/operation/context.rb +40 -2
- data/lib/mongo/operation/create_search_indexes/op_msg.rb +2 -2
- data/lib/mongo/operation/delete/op_msg.rb +2 -1
- data/lib/mongo/operation/drop_search_index/op_msg.rb +2 -2
- data/lib/mongo/operation/find/op_msg.rb +45 -0
- data/lib/mongo/operation/get_more/op_msg.rb +33 -0
- data/lib/mongo/operation/insert/op_msg.rb +3 -2
- data/lib/mongo/operation/insert/result.rb +4 -2
- data/lib/mongo/operation/list_collections/result.rb +1 -1
- data/lib/mongo/operation/map_reduce/result.rb +1 -1
- data/lib/mongo/operation/op_msg_base.rb +3 -1
- data/lib/mongo/operation/result.rb +26 -5
- data/lib/mongo/operation/shared/executable.rb +12 -1
- data/lib/mongo/operation/shared/op_msg_executable.rb +4 -1
- data/lib/mongo/operation/shared/response_handling.rb +3 -3
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
- data/lib/mongo/operation/shared/timed.rb +52 -0
- data/lib/mongo/operation/shared/write.rb +4 -1
- data/lib/mongo/operation/update/op_msg.rb +2 -1
- data/lib/mongo/operation/update_search_index/op_msg.rb +2 -2
- data/lib/mongo/operation.rb +1 -0
- data/lib/mongo/protocol/message.rb +1 -4
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/retryable/read_worker.rb +69 -29
- data/lib/mongo/retryable/write_worker.rb +49 -18
- data/lib/mongo/retryable.rb +8 -2
- data/lib/mongo/server/connection.rb +11 -5
- data/lib/mongo/server/connection_base.rb +22 -2
- data/lib/mongo/server/connection_pool.rb +32 -14
- data/lib/mongo/server/description/features.rb +1 -1
- data/lib/mongo/server/description.rb +18 -5
- data/lib/mongo/server/monitor.rb +7 -4
- data/lib/mongo/server/pending_connection.rb +7 -3
- data/lib/mongo/server/{round_trip_time_averager.rb → round_trip_time_calculator.rb} +25 -7
- data/lib/mongo/server.rb +11 -6
- data/lib/mongo/server_selector/base.rb +25 -9
- data/lib/mongo/session.rb +78 -9
- data/lib/mongo/socket/ssl.rb +109 -17
- data/lib/mongo/socket/tcp.rb +40 -6
- data/lib/mongo/socket.rb +154 -25
- data/lib/mongo/uri/options_mapper.rb +1 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +1 -0
- data/spec/atlas/atlas_connectivity_spec.rb +4 -0
- data/spec/atlas/operations_spec.rb +4 -0
- data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +2 -1
- data/spec/integration/client_side_encryption/auto_encryption_spec.rb +494 -487
- data/spec/integration/client_side_encryption/on_demand_aws_credentials_spec.rb +1 -1
- data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +66 -22
- data/spec/integration/client_side_operations_timeout/encryption_prose_spec.rb +131 -0
- data/spec/integration/connection_pool_populator_spec.rb +2 -0
- data/spec/integration/cursor_pinning_spec.rb +15 -60
- data/spec/integration/cursor_reaping_spec.rb +1 -1
- data/spec/integration/docs_examples_spec.rb +1 -1
- data/spec/integration/operation_failure_code_spec.rb +1 -1
- data/spec/integration/operation_failure_message_spec.rb +3 -3
- data/spec/integration/retryable_errors_spec.rb +2 -2
- data/spec/integration/sdam_error_handling_spec.rb +2 -1
- data/spec/integration/search_indexes_prose_spec.rb +4 -0
- data/spec/integration/server_spec.rb +4 -3
- data/spec/integration/transactions_api_examples_spec.rb +2 -0
- data/spec/kerberos/kerberos_spec.rb +4 -0
- data/spec/lite_spec_helper.rb +3 -1
- data/spec/mongo/auth/user/view_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +1 -1
- data/spec/mongo/client_encryption_spec.rb +1 -0
- data/spec/mongo/client_spec.rb +158 -4
- data/spec/mongo/collection/view/aggregation_spec.rb +14 -39
- data/spec/mongo/collection/view/change_stream_spec.rb +3 -3
- data/spec/mongo/collection_spec.rb +5 -6
- data/spec/mongo/crypt/auto_encrypter_spec.rb +14 -12
- data/spec/mongo/crypt/data_key_context_spec.rb +3 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +2 -2
- data/spec/mongo/crypt/handle_spec.rb +1 -1
- data/spec/mongo/cursor_spec.rb +26 -9
- data/spec/mongo/error/operation_failure_heavy_spec.rb +2 -2
- data/spec/mongo/operation/context_spec.rb +79 -0
- data/spec/mongo/operation/create/op_msg_spec.rb +106 -110
- data/spec/mongo/operation/delete/op_msg_spec.rb +6 -5
- data/spec/mongo/operation/find/op_msg_spec.rb +66 -0
- data/spec/mongo/operation/get_more/op_msg_spec.rb +65 -0
- data/spec/mongo/operation/insert/op_msg_spec.rb +128 -131
- data/spec/mongo/operation/shared/csot/examples.rb +113 -0
- data/spec/mongo/query_cache_spec.rb +243 -225
- data/spec/mongo/retryable_spec.rb +1 -0
- data/spec/mongo/server/round_trip_time_calculator_spec.rb +120 -0
- data/spec/mongo/socket/ssl_spec.rb +0 -10
- data/spec/runners/change_streams/test.rb +2 -2
- data/spec/runners/crud/operation.rb +1 -1
- data/spec/runners/crud/verifier.rb +3 -1
- data/spec/runners/transactions/operation.rb +4 -6
- data/spec/runners/unified/ambiguous_operations.rb +13 -0
- data/spec/runners/unified/assertions.rb +4 -0
- data/spec/runners/unified/change_stream_operations.rb +14 -24
- data/spec/runners/unified/crud_operations.rb +82 -59
- data/spec/runners/unified/ddl_operations.rb +38 -7
- data/spec/runners/unified/grid_fs_operations.rb +37 -2
- data/spec/runners/unified/support_operations.rb +43 -4
- data/spec/runners/unified/test.rb +22 -10
- data/spec/runners/unified.rb +1 -1
- data/spec/solo/clean_exit_spec.rb +2 -0
- data/spec/spec_tests/client_side_operations_timeout_spec.rb +15 -0
- data/spec/spec_tests/data/change_streams_unified/change-streams-clusterTime.yml +3 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-disambiguatedPaths.yml +3 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +3 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +1 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1 -1
- data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/badQueries.yml +2 -1
- data/spec/spec_tests/data/client_side_encryption/timeoutMS.yml +67 -0
- data/spec/spec_tests/data/client_side_operations_timeout/bulkWrite.yml +87 -0
- data/spec/spec_tests/data/client_side_operations_timeout/change-streams.yml +358 -0
- data/spec/spec_tests/data/client_side_operations_timeout/close-cursors.yml +129 -0
- data/spec/spec_tests/data/client_side_operations_timeout/command-execution.yml +250 -0
- data/spec/spec_tests/data/client_side_operations_timeout/convenient-transactions.yml +113 -0
- data/spec/spec_tests/data/client_side_operations_timeout/cursors.yml +70 -0
- data/spec/spec_tests/data/client_side_operations_timeout/deprecated-options.yml +3982 -0
- data/spec/spec_tests/data/client_side_operations_timeout/error-transformations.yml +96 -0
- data/spec/spec_tests/data/client_side_operations_timeout/global-timeoutMS.yml +3236 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-advanced.yml +207 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-delete.yml +152 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-download.yml +182 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-find.yml +100 -0
- data/spec/spec_tests/data/client_side_operations_timeout/gridfs-upload.yml +249 -0
- data/spec/spec_tests/data/client_side_operations_timeout/legacy-timeouts.yml +204 -0
- data/spec/spec_tests/data/client_side_operations_timeout/non-tailable-cursors.yml +307 -0
- data/spec/spec_tests/data/client_side_operations_timeout/override-collection-timeoutMS.yml +1877 -0
- data/spec/spec_tests/data/client_side_operations_timeout/override-operation-timeoutMS.yml +1918 -0
- data/spec/spec_tests/data/client_side_operations_timeout/retryability-legacy-timeouts.yml +1676 -0
- data/spec/spec_tests/data/client_side_operations_timeout/retryability-timeoutMS.yml +2824 -0
- data/spec/spec_tests/data/client_side_operations_timeout/sessions-inherit-timeoutMS.yml +168 -0
- data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-operation-timeoutMS.yml +171 -0
- data/spec/spec_tests/data/client_side_operations_timeout/sessions-override-timeoutMS.yml +168 -0
- data/spec/spec_tests/data/client_side_operations_timeout/tailable-awaitData.yml +247 -0
- data/spec/spec_tests/data/client_side_operations_timeout/tailable-non-awaitData.yml +181 -0
- data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +4 -0
- data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +4 -0
- data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +29 -0
- data/spec/spec_tests/server_selection_rtt_spec.rb +6 -6
- data/spec/support/certificates/atlas-ocsp-ca.crt +81 -83
- data/spec/support/certificates/atlas-ocsp.crt +107 -107
- data/spec/support/cluster_tools.rb +3 -3
- data/spec/support/common_shortcuts.rb +2 -2
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-Date.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalNoPrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DecimalPrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoubleNoPrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-DoublePrecision.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-Int.json +1 -1
- data/spec/support/crypt/encrypted_fields/range-encryptedFields-Long.json +1 -1
- data/spec/support/shared/session.rb +2 -2
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/utils.rb +3 -1
- metadata +78 -91
- data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -242
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -423
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -183
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -240
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -236
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -253
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1688
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -294
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -906
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1685
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1681
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1698
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -330
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -425
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -227
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -328
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -320
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -337
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -914
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -293
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -519
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -912
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -908
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -925
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -326
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -425
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -225
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -324
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -320
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -339
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -242
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -424
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -183
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -240
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -236
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -255
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -242
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -423
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -183
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -240
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -236
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -255
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -44
@@ -18,242 +18,247 @@ require 'mongo/error/read_write_retryable'
|
|
18
18
|
|
19
19
|
module Mongo
|
20
20
|
class Error
|
21
|
-
|
22
21
|
# Raised when an operation fails for some reason.
|
23
|
-
#
|
24
|
-
# @since 2.0.0
|
25
22
|
class OperationFailure < Error
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
# Implements the behavior for an OperationFailure error. Other errors
|
24
|
+
# (e.g. ServerTimeoutError) may also implement this, so that they may
|
25
|
+
# be recognized and treated as OperationFailure errors.
|
26
|
+
module OperationFailure::Family
|
27
|
+
extend Forwardable
|
28
|
+
include SdamErrorDetection
|
29
|
+
include ReadWriteRetryable
|
29
30
|
|
30
|
-
|
31
|
+
def_delegators :@result, :operation_time
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
# @!method connection_description
|
34
|
+
#
|
35
|
+
# @return [ Server::Description ] Server description of the server that
|
36
|
+
# the operation that this exception refers to was performed on.
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
def_delegator :@result, :connection_description
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
# @return [ Integer ] The error code parsed from the document.
|
42
|
+
#
|
43
|
+
# @since 2.6.0
|
44
|
+
attr_reader :code
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
# @return [ String ] The error code name parsed from the document.
|
47
|
+
#
|
48
|
+
# @since 2.6.0
|
49
|
+
attr_reader :code_name
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
# @return [ String ] The server-returned error message
|
52
|
+
# parsed from the response.
|
53
|
+
#
|
54
|
+
# @api experimental
|
55
|
+
attr_reader :server_message
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
57
|
+
# Error codes and code names that should result in a failing getMore
|
58
|
+
# command on a change stream NOT being resumed.
|
59
|
+
#
|
60
|
+
# @api private
|
61
|
+
CHANGE_STREAM_RESUME_ERRORS = [
|
62
|
+
{code_name: 'HostUnreachable', code: 6},
|
63
|
+
{code_name: 'HostNotFound', code: 7},
|
64
|
+
{code_name: 'NetworkTimeout', code: 89},
|
65
|
+
{code_name: 'ShutdownInProgress', code: 91},
|
66
|
+
{code_name: 'PrimarySteppedDown', code: 189},
|
67
|
+
{code_name: 'ExceededTimeLimit', code: 262},
|
68
|
+
{code_name: 'SocketException', code: 9001},
|
69
|
+
{code_name: 'NotMaster', code: 10107},
|
70
|
+
{code_name: 'InterruptedAtShutdown', code: 11600},
|
71
|
+
{code_name: 'InterruptedDueToReplStateChange', code: 11602},
|
72
|
+
{code_name: 'NotPrimaryNoSecondaryOk', code: 13435},
|
73
|
+
{code_name: 'NotMasterOrSecondary', code: 13436},
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
{code_name: 'StaleShardVersion', code: 63},
|
76
|
+
{code_name: 'FailedToSatisfyReadPreference', code: 133},
|
77
|
+
{code_name: 'StaleEpoch', code: 150},
|
78
|
+
{code_name: 'RetryChangeStream', code: 234},
|
79
|
+
{code_name: 'StaleConfig', code: 13388},
|
80
|
+
].freeze
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
# Change stream can be resumed when these error messages are encountered.
|
83
|
+
#
|
84
|
+
# @since 2.6.0
|
85
|
+
# @api private
|
86
|
+
CHANGE_STREAM_RESUME_MESSAGES = ReadWriteRetryable::WRITE_RETRY_MESSAGES
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
88
|
+
# Can the change stream on which this error occurred be resumed,
|
89
|
+
# provided the operation that triggered this error was a getMore?
|
90
|
+
#
|
91
|
+
# @example Is the error resumable for the change stream?
|
92
|
+
# error.change_stream_resumable?
|
93
|
+
#
|
94
|
+
# @return [ true, false ] Whether the error is resumable.
|
95
|
+
#
|
96
|
+
# @since 2.6.0
|
97
|
+
def change_stream_resumable?
|
98
|
+
if @result && @result.is_a?(Mongo::Operation::GetMore::Result)
|
99
|
+
# CursorNotFound exceptions are always resumable because the server
|
100
|
+
# is not aware of the cursor id, and thus cannot determine if
|
101
|
+
# the cursor is a change stream and cannot add the
|
102
|
+
# ResumableChangeStreamError label.
|
103
|
+
return true if code == 43
|
103
104
|
|
104
|
-
|
105
|
-
|
106
|
-
|
105
|
+
# Connection description is not populated for unacknowledged writes.
|
106
|
+
if connection_description.max_wire_version >= 9
|
107
|
+
label?('ResumableChangeStreamError')
|
108
|
+
else
|
109
|
+
change_stream_resumable_code?
|
110
|
+
end
|
107
111
|
else
|
108
|
-
|
112
|
+
false
|
109
113
|
end
|
110
|
-
else
|
111
|
-
false
|
112
114
|
end
|
113
|
-
end
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
def change_stream_resumable_code?
|
117
|
+
CHANGE_STREAM_RESUME_ERRORS.any? { |e| e[:code] == code }
|
118
|
+
end
|
119
|
+
private :change_stream_resumable_code?
|
119
120
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
121
|
+
# @return [ true | false ] Whether the failure includes a write
|
122
|
+
# concern error. A failure may have a top level error and a write
|
123
|
+
# concern error or either one of the two.
|
124
|
+
#
|
125
|
+
# @since 2.10.0
|
126
|
+
def write_concern_error?
|
127
|
+
!!@write_concern_error_document
|
128
|
+
end
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
130
|
+
# Returns the write concern error document as it was reported by the
|
131
|
+
# server, if any.
|
132
|
+
#
|
133
|
+
# @return [ Hash | nil ] Write concern error as reported to the server.
|
134
|
+
attr_reader :write_concern_error_document
|
134
135
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
136
|
+
# @return [ Integer | nil ] The error code for the write concern error,
|
137
|
+
# if a write concern error is present and has a code.
|
138
|
+
#
|
139
|
+
# @since 2.10.0
|
140
|
+
attr_reader :write_concern_error_code
|
140
141
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
142
|
+
# @return [ String | nil ] The code name for the write concern error,
|
143
|
+
# if a write concern error is present and has a code name.
|
144
|
+
#
|
145
|
+
# @since 2.10.0
|
146
|
+
attr_reader :write_concern_error_code_name
|
146
147
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
148
|
+
# @return [ String | nil ] The details of the error.
|
149
|
+
# For WriteConcernErrors this is `document['writeConcernError']['errInfo']`.
|
150
|
+
# For WriteErrors this is `document['writeErrors'][0]['errInfo']`.
|
151
|
+
# For all other errors this is nil.
|
152
|
+
attr_reader :details
|
152
153
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
154
|
+
# @return [ BSON::Document | nil ] The server-returned error document.
|
155
|
+
#
|
156
|
+
# @api experimental
|
157
|
+
attr_reader :document
|
157
158
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
#
|
163
|
-
# @example Create the error object with a code and a code name
|
164
|
-
# OperationFailure.new(message, result, :code => code, :code_name => code_name)
|
165
|
-
#
|
166
|
-
# @param [ String ] message The error message.
|
167
|
-
# @param [ Operation::Result ] result The result object.
|
168
|
-
# @param [ Hash ] options Additional parameters.
|
169
|
-
#
|
170
|
-
# @option options [ Integer ] :code Error code.
|
171
|
-
# @option options [ String ] :code_name Error code name.
|
172
|
-
# @option options [ BSON::Document ] :document The server-returned
|
173
|
-
# error document.
|
174
|
-
# @option options [ String ] server_message The server-returned
|
175
|
-
# error message parsed from the response.
|
176
|
-
# @option options [ Hash ] :write_concern_error_document The
|
177
|
-
# server-supplied write concern error document, if any.
|
178
|
-
# @option options [ Integer ] :write_concern_error_code Error code for
|
179
|
-
# write concern error, if any.
|
180
|
-
# @option options [ String ] :write_concern_error_code_name Error code
|
181
|
-
# name for write concern error, if any.
|
182
|
-
# @option options [ Array<String> ] :write_concern_error_labels Error
|
183
|
-
# labels for the write concern error, if any.
|
184
|
-
# @option options [ Array<String> ] :labels The set of labels associated
|
185
|
-
# with the error.
|
186
|
-
# @option options [ true | false ] :wtimeout Whether the error is a wtimeout.
|
187
|
-
def initialize(message = nil, result = nil, options = {})
|
188
|
-
@details = retrieve_details(options[:document])
|
189
|
-
super(append_details(message, @details))
|
159
|
+
# @return [ Operation::Result ] the result object for the operation.
|
160
|
+
#
|
161
|
+
# @api private
|
162
|
+
attr_reader :result
|
190
163
|
|
191
|
-
|
192
|
-
|
193
|
-
@
|
194
|
-
@
|
195
|
-
@
|
196
|
-
|
197
|
-
@
|
198
|
-
@
|
199
|
-
@
|
200
|
-
|
201
|
-
@
|
202
|
-
|
164
|
+
# Create the operation failure.
|
165
|
+
#
|
166
|
+
# @param [ String ] message The error message.
|
167
|
+
# @param [ Operation::Result ] result The result object.
|
168
|
+
# @param [ Hash ] options Additional parameters.
|
169
|
+
#
|
170
|
+
# @option options [ Integer ] :code Error code.
|
171
|
+
# @option options [ String ] :code_name Error code name.
|
172
|
+
# @option options [ BSON::Document ] :document The server-returned
|
173
|
+
# error document.
|
174
|
+
# @option options [ String ] server_message The server-returned
|
175
|
+
# error message parsed from the response.
|
176
|
+
# @option options [ Hash ] :write_concern_error_document The
|
177
|
+
# server-supplied write concern error document, if any.
|
178
|
+
# @option options [ Integer ] :write_concern_error_code Error code for
|
179
|
+
# write concern error, if any.
|
180
|
+
# @option options [ String ] :write_concern_error_code_name Error code
|
181
|
+
# name for write concern error, if any.
|
182
|
+
# @option options [ Array<String> ] :write_concern_error_labels Error
|
183
|
+
# labels for the write concern error, if any.
|
184
|
+
# @option options [ Array<String> ] :labels The set of labels associated
|
185
|
+
# with the error.
|
186
|
+
# @option options [ true | false ] :wtimeout Whether the error is a wtimeout.
|
187
|
+
def initialize(message = nil, result = nil, options = {})
|
188
|
+
@details = retrieve_details(options[:document])
|
189
|
+
super(append_details(message, @details))
|
203
190
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
191
|
+
@result = result
|
192
|
+
@code = options[:code]
|
193
|
+
@code_name = options[:code_name]
|
194
|
+
@write_concern_error_document = options[:write_concern_error_document]
|
195
|
+
@write_concern_error_code = options[:write_concern_error_code]
|
196
|
+
@write_concern_error_code_name = options[:write_concern_error_code_name]
|
197
|
+
@write_concern_error_labels = options[:write_concern_error_labels] || []
|
198
|
+
@labels = options[:labels] || []
|
199
|
+
@wtimeout = !!options[:wtimeout]
|
200
|
+
@document = options[:document]
|
201
|
+
@server_message = options[:server_message]
|
202
|
+
end
|
212
203
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
204
|
+
# Whether the error is a write concern timeout.
|
205
|
+
#
|
206
|
+
# @return [ true | false ] Whether the error is a write concern timeout.
|
207
|
+
#
|
208
|
+
# @since 2.7.1
|
209
|
+
def wtimeout?
|
210
|
+
@wtimeout
|
211
|
+
end
|
221
212
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
#
|
232
|
-
#
|
233
|
-
|
234
|
-
|
213
|
+
# Whether the error is MaxTimeMSExpired.
|
214
|
+
#
|
215
|
+
# @return [ true | false ] Whether the error is MaxTimeMSExpired.
|
216
|
+
#
|
217
|
+
# @since 2.10.0
|
218
|
+
def max_time_ms_expired?
|
219
|
+
code == 50 # MaxTimeMSExpired
|
220
|
+
end
|
221
|
+
|
222
|
+
# Whether the error is caused by an attempted retryable write
|
223
|
+
# on a storage engine that does not support retryable writes.
|
224
|
+
#
|
225
|
+
# @return [ true | false ] Whether the error is caused by an attempted
|
226
|
+
# retryable write on a storage engine that does not support retryable writes.
|
227
|
+
#
|
228
|
+
# @since 2.10.0
|
229
|
+
def unsupported_retryable_write?
|
230
|
+
# code 20 is IllegalOperation.
|
231
|
+
# Note that the document is expected to be a BSON::Document, thus
|
232
|
+
# either having string keys or providing indifferent access.
|
233
|
+
code == 20 && server_message&.start_with?("Transaction numbers") || false
|
234
|
+
end
|
235
235
|
|
236
|
-
|
236
|
+
private
|
237
237
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
238
|
+
# Retrieve the details from a document
|
239
|
+
#
|
240
|
+
# @return [ Hash | nil ] the details extracted from the document
|
241
|
+
def retrieve_details(document)
|
242
|
+
return nil unless document
|
243
|
+
if wce = document['writeConcernError']
|
244
|
+
return wce['errInfo']
|
245
|
+
elsif we = document['writeErrors']&.first
|
246
|
+
return we['errInfo']
|
247
|
+
end
|
247
248
|
end
|
248
|
-
end
|
249
249
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
250
|
+
# Append the details to the message
|
251
|
+
#
|
252
|
+
# @return [ String ] the message with the details appended to it
|
253
|
+
def append_details(message, details)
|
254
|
+
return message unless details && message
|
255
|
+
message + " -- #{details.to_json}"
|
256
|
+
end
|
256
257
|
end
|
258
|
+
|
259
|
+
# OperationFailure is the canonical implementor of the
|
260
|
+
# OperationFailure::Family concern.
|
261
|
+
include OperationFailure::Family
|
257
262
|
end
|
258
263
|
end
|
259
264
|
end
|
@@ -15,13 +15,15 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
+
require 'mongo/error/timeout_error'
|
19
|
+
|
18
20
|
module Mongo
|
19
21
|
class Error
|
20
22
|
|
21
23
|
# Raised when a socket connection times out.
|
22
24
|
#
|
23
25
|
# @since 2.0.0
|
24
|
-
class SocketTimeoutError <
|
26
|
+
class SocketTimeoutError < TimeoutError
|
25
27
|
include WriteRetryable
|
26
28
|
include ChangeStreamResumable
|
27
29
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2015-present MongoDB Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Mongo
|
18
|
+
class Error
|
19
|
+
# Raised when a Client Side Operation Timeout times out.
|
20
|
+
class TimeoutError < Error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/mongo/error.rb
CHANGED
@@ -217,7 +217,9 @@ require 'mongo/error/missing_service_id'
|
|
217
217
|
require 'mongo/error/server_api_conflict'
|
218
218
|
require 'mongo/error/server_api_not_supported'
|
219
219
|
require 'mongo/error/server_not_usable'
|
220
|
+
require 'mongo/error/server_timeout_error'
|
220
221
|
require 'mongo/error/transactions_not_supported'
|
222
|
+
require 'mongo/error/timeout_error'
|
221
223
|
require 'mongo/error/unknown_payload_type'
|
222
224
|
require 'mongo/error/unmet_dependency'
|
223
225
|
require 'mongo/error/unsupported_option'
|
data/lib/mongo/grid/fs_bucket.rb
CHANGED
@@ -201,8 +201,8 @@ module Mongo
|
|
201
201
|
# @return [ Result ] The result of the remove.
|
202
202
|
#
|
203
203
|
# @since 2.0.0
|
204
|
-
def delete_one(file)
|
205
|
-
delete(file.id)
|
204
|
+
def delete_one(file, opts = {})
|
205
|
+
delete(file.id, opts)
|
206
206
|
end
|
207
207
|
|
208
208
|
# Remove a single file, identified by its id from the GridFS.
|
@@ -217,9 +217,14 @@ module Mongo
|
|
217
217
|
# @raise [ Error::FileNotFound ] If the file is not found.
|
218
218
|
#
|
219
219
|
# @since 2.1.0
|
220
|
-
def delete(id)
|
221
|
-
|
222
|
-
|
220
|
+
def delete(id, opts = {})
|
221
|
+
timeout_holder = CsotTimeoutHolder.new(operation_timeouts: operation_timeouts(opts))
|
222
|
+
result = files_collection
|
223
|
+
.find({ :_id => id }, @options.merge(timeout_ms: timeout_holder.remaining_timeout_ms))
|
224
|
+
.delete_one(timeout_ms: timeout_holder.remaining_timeout_ms)
|
225
|
+
chunks_collection
|
226
|
+
.find({ :files_id => id }, @options.merge(timeout_ms: timeout_holder.remaining_timeout_ms))
|
227
|
+
.delete_many(timeout_ms: timeout_holder.remaining_timeout_ms)
|
223
228
|
raise Error::FileNotFound.new(id, :id) if result.n == 0
|
224
229
|
result
|
225
230
|
end
|
@@ -485,9 +490,10 @@ module Mongo
|
|
485
490
|
end
|
486
491
|
|
487
492
|
# Drop the collections that implement this bucket.
|
488
|
-
def drop
|
489
|
-
|
490
|
-
|
493
|
+
def drop(opts = {})
|
494
|
+
context = Operation::Context.new(operation_timeouts: operation_timeouts(opts))
|
495
|
+
files_collection.drop(timeout_ms: context.remaining_timeout_ms)
|
496
|
+
chunks_collection.drop(timeout_ms: context.remaining_timeout_ms)
|
491
497
|
end
|
492
498
|
|
493
499
|
private
|
@@ -512,12 +518,24 @@ module Mongo
|
|
512
518
|
"#{prefix}.#{Grid::File::Info::COLLECTION}"
|
513
519
|
end
|
514
520
|
|
515
|
-
def ensure_indexes!
|
516
|
-
|
521
|
+
def ensure_indexes!(timeout_holder = nil)
|
522
|
+
fc_idx = files_collection.find(
|
523
|
+
{},
|
524
|
+
limit: 1,
|
525
|
+
projection: { _id: 1 },
|
526
|
+
timeout_ms: timeout_holder&.remaining_timeout_ms
|
527
|
+
).first
|
528
|
+
if fc_idx.nil?
|
517
529
|
create_index_if_missing!(files_collection, FSBucket::FILES_INDEX)
|
518
530
|
end
|
519
531
|
|
520
|
-
|
532
|
+
cc_idx = chunks_collection.find(
|
533
|
+
{},
|
534
|
+
limit: 1,
|
535
|
+
projection: { _id: 1 },
|
536
|
+
timeout_ms: timeout_holder&.remaining_timeout_ms
|
537
|
+
).first
|
538
|
+
if cc_idx.nil?
|
521
539
|
create_index_if_missing!(chunks_collection, FSBucket::CHUNKS_INDEX, :unique => true)
|
522
540
|
end
|
523
541
|
end
|
@@ -528,7 +546,7 @@ module Mongo
|
|
528
546
|
if indexes_view.get(index_spec).nil?
|
529
547
|
indexes_view.create_one(index_spec, options)
|
530
548
|
end
|
531
|
-
rescue Mongo::Error::OperationFailure => e
|
549
|
+
rescue Mongo::Error::OperationFailure::Family => e
|
532
550
|
# proceed with index creation if a NamespaceNotFound error is thrown
|
533
551
|
if e.code == 26
|
534
552
|
indexes_view.create_one(index_spec, options)
|
@@ -537,6 +555,21 @@ module Mongo
|
|
537
555
|
end
|
538
556
|
end
|
539
557
|
end
|
558
|
+
|
559
|
+
# @return [ Hash ] timeout_ms value set on the operation level (if any),
|
560
|
+
# and/or timeout_ms that is set on collection/database/client level (if any).
|
561
|
+
#
|
562
|
+
# @api private
|
563
|
+
def operation_timeouts(opts = {})
|
564
|
+
# TODO: We should re-evaluate if we need two timeouts separately.
|
565
|
+
{}.tap do |result|
|
566
|
+
if opts[:timeout_ms].nil?
|
567
|
+
result[:inherited_timeout_ms] = database.timeout_ms
|
568
|
+
else
|
569
|
+
result[:operation_timeout_ms] = opts[:timeout_ms]
|
570
|
+
end
|
571
|
+
end
|
572
|
+
end
|
540
573
|
end
|
541
574
|
end
|
542
575
|
end
|
@@ -59,6 +59,12 @@ module Mongo
|
|
59
59
|
@file_id = @options.delete(:file_id)
|
60
60
|
@options.freeze
|
61
61
|
@open = true
|
62
|
+
@timeout_holder = CsotTimeoutHolder.new(
|
63
|
+
operation_timeouts: {
|
64
|
+
operation_timeout_ms: options[:timeout_ms],
|
65
|
+
inherited_timeout_ms: fs.database.timeout_ms
|
66
|
+
}
|
67
|
+
)
|
62
68
|
end
|
63
69
|
|
64
70
|
# Iterate through chunk data streamed from the FSBucket.
|
@@ -178,7 +184,11 @@ module Mongo
|
|
178
184
|
# @since 2.1.0
|
179
185
|
def file_info
|
180
186
|
@file_info ||= begin
|
181
|
-
doc = options[:file_info_doc] ||
|
187
|
+
doc = options[:file_info_doc] ||
|
188
|
+
fs.files_collection.find(
|
189
|
+
{ _id: file_id },
|
190
|
+
{ timeout_ms: @timeout_holder.remaining_timeout_ms! }
|
191
|
+
).first
|
182
192
|
if doc
|
183
193
|
File::Info.new(Options::Mapper.transform(doc, File::Info::MAPPINGS.invert))
|
184
194
|
else
|
@@ -209,6 +219,10 @@ module Mongo
|
|
209
219
|
else
|
210
220
|
options
|
211
221
|
end
|
222
|
+
if @timeout_holder.csot?
|
223
|
+
opts[:timeout_ms] = @timeout_holder.remaining_timeout_ms!
|
224
|
+
opts[:timeout_mode] = :cursor_lifetime
|
225
|
+
end
|
212
226
|
|
213
227
|
fs.chunks_collection.find({ :files_id => file_id }, opts).sort(:n => 1)
|
214
228
|
end
|