mongo 2.20.0 → 2.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +40 -1
- data/Rakefile +59 -23
- 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/config.rb +2 -2
- 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/base_worker.rb +28 -3
- data/lib/mongo/retryable/read_worker.rb +76 -35
- data/lib/mongo/retryable/write_worker.rb +53 -22
- 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 +25 -8
- 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 +131 -18
- 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 -5
- data/lib/mongo.rb +1 -0
- data/mongo.gemspec +8 -11
- 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 +67 -20
- 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/retryable_reads_errors_spec.rb +35 -23
- data/spec/integration/sdam_error_handling_spec.rb +4 -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 -11
- 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_crud_spec.rb +1 -0
- 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/connection_spec.rb +22 -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/fle2v2-BypassQueryAnalysis.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Compact.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-CreateCollection.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-DecryptExistingData.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Delete.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-EncryptedFieldsMap.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-jsonSchema.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFieldsMap-defaults.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-FindOneAndUpdate.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Indexed.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Unindexed.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-MissingKey.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-NoEncryption.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Update.yml +1 -0
- data/spec/spec_tests/data/client_side_encryption/fle2v2-validatorAndPartialFieldExpression.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 +6 -0
- data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +6 -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/spec_tests/transactions_unified_spec.rb +2 -1
- data/spec/support/certificates/atlas-ocsp-ca.crt +89 -79
- data/spec/support/certificates/atlas-ocsp.crt +117 -122
- data/spec/support/certificates/retrieve-atlas-cert +1 -1
- 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 +88 -173
- checksums.yaml.gz.sig +0 -0
- data/spec/mongo/server/round_trip_time_averager_spec.rb +0 -48
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/bin/s3-copy +0 -45
- data/spec/shared/bin/s3-upload +0 -69
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -231
- data/spec/shared/lib/mrss/constraints.rb +0 -378
- data/spec/shared/lib/mrss/docker_runner.rb +0 -298
- data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
- data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
- data/spec/shared/lib/mrss/session_registry.rb +0 -69
- data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
- data/spec/shared/lib/mrss/utils.rb +0 -37
- data/spec/shared/share/Dockerfile.erb +0 -281
- data/spec/shared/share/haproxy-1.conf +0 -16
- data/spec/shared/share/haproxy-2.conf +0 -17
- data/spec/shared/shlib/config.sh +0 -27
- data/spec/shared/shlib/distro.sh +0 -74
- data/spec/shared/shlib/server.sh +0 -417
- data/spec/shared/shlib/set_env.sh +0 -146
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +0 -241
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +0 -422
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +0 -182
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +0 -239
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +0 -235
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +0 -252
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +0 -1687
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +0 -293
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +0 -905
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +0 -1684
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +0 -1680
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +0 -1697
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +0 -329
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +0 -424
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +0 -226
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +0 -327
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +0 -319
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +0 -336
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +0 -913
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +0 -292
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +0 -518
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +0 -911
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +0 -907
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +0 -924
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +0 -325
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +0 -424
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +0 -224
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +0 -323
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +0 -319
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +0 -338
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +0 -241
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +0 -423
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +0 -182
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +0 -239
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +0 -235
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +0 -254
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +0 -241
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +0 -422
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +0 -182
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +0 -239
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +0 -235
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +0 -254
- data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +0 -43
- data/spec/support/faas/app/aws_lambda/mongodb/Gemfile.lock +0 -19
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -3
@@ -42,7 +42,7 @@ module Mongo
|
|
42
42
|
# Adds error labels to exceptions raised in the yielded to block,
|
43
43
|
# which should perform MongoDB operations and raise Mongo::Errors on
|
44
44
|
# failure. This method handles network errors (Error::SocketError)
|
45
|
-
# and server-side errors (Error::OperationFailure); it does not
|
45
|
+
# and server-side errors (Error::OperationFailure::Family); it does not
|
46
46
|
# handle server selection errors (Error::NoServerAvailable), for which
|
47
47
|
# labels are added in the server selection code.
|
48
48
|
#
|
@@ -65,7 +65,7 @@ module Mongo
|
|
65
65
|
rescue Mongo::Error::SocketTimeoutError => e
|
66
66
|
maybe_add_retryable_write_error_label!(e, connection, context)
|
67
67
|
raise e
|
68
|
-
rescue Mongo::Error::OperationFailure => e
|
68
|
+
rescue Mongo::Error::OperationFailure::Family => e
|
69
69
|
if context.committing_transaction?
|
70
70
|
if e.write_retryable? || e.wtimeout? || (e.write_concern_error? &&
|
71
71
|
!Session::UNLABELED_WRITE_CONCERN_CODES.include?(e.write_concern_error_code)
|
@@ -104,7 +104,7 @@ module Mongo
|
|
104
104
|
# raised during execution of operations on servers.
|
105
105
|
def add_server_diagnostics(connection)
|
106
106
|
yield
|
107
|
-
rescue Error::SocketError, Error::SocketTimeoutError
|
107
|
+
rescue Error::SocketError, Error::SocketTimeoutError, Error::TimeoutError
|
108
108
|
# Diagnostics should have already been added by the connection code,
|
109
109
|
# do not add them again.
|
110
110
|
raise
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongo
|
4
|
+
module Operation
|
5
|
+
# Defines the behavior of operations that have the default timeout
|
6
|
+
# behavior described by the client-side operation timeouts (CSOT)
|
7
|
+
# spec.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
module Timed
|
11
|
+
# If a timeout is active (as defined by the current context), and it has
|
12
|
+
# not yet expired, add :maxTimeMS to the spec.
|
13
|
+
#
|
14
|
+
# @param [ Hash ] spec The spec to modify
|
15
|
+
# @param [ Connection ] connection The connection that will be used to
|
16
|
+
# execute the operation
|
17
|
+
#
|
18
|
+
# @return [ Hash ] the spec
|
19
|
+
#
|
20
|
+
# @raises [ Mongo::Error::TimeoutError ] if the current timeout has
|
21
|
+
# expired.
|
22
|
+
def apply_relevant_timeouts_to(spec, connection)
|
23
|
+
with_max_time(connection) do |max_time_sec|
|
24
|
+
return spec if max_time_sec.nil?
|
25
|
+
return spec if connection.description.mongocryptd?
|
26
|
+
|
27
|
+
spec.tap { spec[:maxTimeMS] = (max_time_sec * 1_000).to_i }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# A helper method that computes the remaining timeout (in seconds) and
|
32
|
+
# yields it to the associated block. If no timeout is present, yields
|
33
|
+
# nil. If the timeout has expired, raises Mongo::Error::TimeoutError.
|
34
|
+
#
|
35
|
+
# @param [ Connection ] connection The connection that will be used to
|
36
|
+
# execute the operation
|
37
|
+
#
|
38
|
+
# @return [ Hash ] the result of yielding to the block (which must be
|
39
|
+
# a Hash)
|
40
|
+
def with_max_time(connection)
|
41
|
+
if context&.timeout?
|
42
|
+
max_time_sec = context.remaining_timeout_sec - connection.server.minimum_round_trip_time
|
43
|
+
raise Mongo::Error::TimeoutError if max_time_sec <= 0
|
44
|
+
|
45
|
+
yield max_time_sec
|
46
|
+
else
|
47
|
+
yield nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -35,7 +35,10 @@ module Mongo
|
|
35
35
|
#
|
36
36
|
# @since 2.5.2
|
37
37
|
def execute(server, context:)
|
38
|
-
server.with_connection(
|
38
|
+
server.with_connection(
|
39
|
+
connection_global_id: context.connection_global_id,
|
40
|
+
context: context
|
41
|
+
) do |connection|
|
39
42
|
execute_with_connection(connection, context: context)
|
40
43
|
end
|
41
44
|
end
|
@@ -45,7 +45,8 @@ module Mongo
|
|
45
45
|
def message(connection)
|
46
46
|
updates = validate_updates(connection, send(IDENTIFIER))
|
47
47
|
section = Protocol::Msg::Section1.new(IDENTIFIER, updates)
|
48
|
-
|
48
|
+
cmd = apply_relevant_timeouts_to(command(connection), connection)
|
49
|
+
Protocol::Msg.new(flags, {}, cmd, section)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
@@ -14,11 +14,11 @@ module Mongo
|
|
14
14
|
# Returns the command to send to the database, describing the
|
15
15
|
# desired updateSearchIndex operation.
|
16
16
|
#
|
17
|
-
# @param [
|
17
|
+
# @param [ Connection ] _connection the connection that will receive the
|
18
18
|
# command
|
19
19
|
#
|
20
20
|
# @return [ Hash ] the selector
|
21
|
-
def selector(
|
21
|
+
def selector(_connection)
|
22
22
|
{
|
23
23
|
updateSearchIndex: coll_name,
|
24
24
|
:$db => db_name,
|
data/lib/mongo/operation.rb
CHANGED
@@ -22,6 +22,7 @@ require 'mongo/operation/shared/specifiable'
|
|
22
22
|
require 'mongo/operation/shared/validatable'
|
23
23
|
require 'mongo/operation/shared/object_id_generator'
|
24
24
|
require 'mongo/operation/shared/op_msg_executable'
|
25
|
+
require 'mongo/operation/shared/timed'
|
25
26
|
|
26
27
|
require 'mongo/operation/op_msg_base'
|
27
28
|
require 'mongo/operation/command'
|
@@ -244,10 +244,7 @@ module Mongo
|
|
244
244
|
# timeout option. For compatibility with whoever might call this
|
245
245
|
# method with some other IO-like object, pass options only when they
|
246
246
|
# are not empty.
|
247
|
-
read_options =
|
248
|
-
if timeout = options[:socket_timeout]
|
249
|
-
read_options[:timeout] = timeout
|
250
|
-
end
|
247
|
+
read_options = options.slice(:timeout, :socket_timeout)
|
251
248
|
|
252
249
|
if read_options.empty?
|
253
250
|
chunk = io.read(16)
|
data/lib/mongo/protocol/msg.rb
CHANGED
@@ -226,7 +226,7 @@ module Mongo
|
|
226
226
|
|
227
227
|
db_name = @main_document[DATABASE_IDENTIFIER]
|
228
228
|
cmd = merge_sections
|
229
|
-
enc_cmd = context.
|
229
|
+
enc_cmd = context.encrypt(db_name, cmd)
|
230
230
|
if cmd.key?('$db') && !enc_cmd.key?('$db')
|
231
231
|
enc_cmd['$db'] = cmd['$db']
|
232
232
|
end
|
@@ -251,7 +251,7 @@ module Mongo
|
|
251
251
|
def maybe_decrypt(context)
|
252
252
|
if context.decrypt?
|
253
253
|
cmd = merge_sections
|
254
|
-
enc_cmd = context.
|
254
|
+
enc_cmd = context.decrypt(cmd)
|
255
255
|
Msg.new(@flags, @options, enc_cmd)
|
256
256
|
else
|
257
257
|
self
|
@@ -49,7 +49,8 @@ module Mongo
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
# Indicate which exception classes that are generally retryable
|
52
|
+
# Indicate which exception classes that are generally retryable
|
53
|
+
# when using modern retries mechanism.
|
53
54
|
#
|
54
55
|
# @return [ Array<Mongo:Error> ] Array of exception classes that are
|
55
56
|
# considered retryable.
|
@@ -58,18 +59,42 @@ module Mongo
|
|
58
59
|
Error::ConnectionPerished,
|
59
60
|
Error::ServerNotUsable,
|
60
61
|
Error::SocketError,
|
61
|
-
Error::SocketTimeoutError
|
62
|
+
Error::SocketTimeoutError,
|
62
63
|
].freeze
|
63
64
|
end
|
64
65
|
|
66
|
+
# Indicate which exception classes that are generally retryable
|
67
|
+
# when using legacy retries mechanism.
|
68
|
+
#
|
69
|
+
# @return [ Array<Mongo:Error> ] Array of exception classes that are
|
70
|
+
# considered retryable.
|
71
|
+
def legacy_retryable_exceptions
|
72
|
+
[
|
73
|
+
Error::ConnectionPerished,
|
74
|
+
Error::ServerNotUsable,
|
75
|
+
Error::SocketError,
|
76
|
+
Error::SocketTimeoutError,
|
77
|
+
Error::PoolClearedError,
|
78
|
+
Error::PoolPausedError,
|
79
|
+
].freeze
|
80
|
+
end
|
81
|
+
|
82
|
+
|
65
83
|
# Tests to see if the given exception instance is of a type that can
|
66
|
-
# be retried.
|
84
|
+
# be retried with modern retry mechanism.
|
67
85
|
#
|
68
86
|
# @return [ true | false ] true if the exception is retryable.
|
69
87
|
def is_retryable_exception?(e)
|
70
88
|
retryable_exceptions.any? { |klass| klass === e }
|
71
89
|
end
|
72
90
|
|
91
|
+
# Tests to see if the given exception instance is of a type that can
|
92
|
+
# be retried with legacy retry mechanism.
|
93
|
+
#
|
94
|
+
# @return [ true | false ] true if the exception is retryable.
|
95
|
+
def is_legacy_retryable_exception?(e)
|
96
|
+
legacy_retryable_exceptions.any? { |klass| klass === e }
|
97
|
+
end
|
73
98
|
# Logs the given deprecation warning the first time it is called for a
|
74
99
|
# given key; after that, it does nothing when given the same key.
|
75
100
|
def deprecation_warning(key, warning)
|
@@ -60,19 +60,21 @@ module Mongo
|
|
60
60
|
# @param [ Mongo::ServerSelector::Selectable ] server_selector Server
|
61
61
|
# selector for the operation.
|
62
62
|
# @param [ CollectionView ] view The +CollectionView+ defining the query.
|
63
|
+
# @param [ Operation::Context | nil ] context the operation context to use
|
64
|
+
# with the cursor.
|
63
65
|
# @param [ Proc ] block The block to execute.
|
64
66
|
#
|
65
67
|
# @return [ Cursor ] The cursor for the result set.
|
66
|
-
def read_with_retry_cursor(session, server_selector, view, &block)
|
67
|
-
read_with_retry(session, server_selector) do |server|
|
68
|
+
def read_with_retry_cursor(session, server_selector, view, context: nil, &block)
|
69
|
+
read_with_retry(session, server_selector, context) do |server|
|
68
70
|
result = yield server
|
69
71
|
|
70
72
|
# RUBY-2367: This will be updated to allow the query cache to
|
71
73
|
# cache cursors with multi-batch results.
|
72
74
|
if QueryCache.enabled? && !view.collection.system_collection?
|
73
|
-
CachingCursor.new(view, result, server, session: session)
|
75
|
+
CachingCursor.new(view, result, server, session: session, context: context)
|
74
76
|
else
|
75
|
-
Cursor.new(view, result, server, session: session)
|
77
|
+
Cursor.new(view, result, server, session: session, context: context)
|
76
78
|
end
|
77
79
|
end
|
78
80
|
end
|
@@ -107,16 +109,18 @@ module Mongo
|
|
107
109
|
# is being run on.
|
108
110
|
# @param [ Mongo::ServerSelector::Selectable | nil ] server_selector
|
109
111
|
# Server selector for the operation.
|
112
|
+
# @param [ Mongo::Operation::Context | nil ] context Context for the
|
113
|
+
# read operation.
|
110
114
|
# @param [ Proc ] block The block to execute.
|
111
115
|
#
|
112
116
|
# @return [ Result ] The result of the operation.
|
113
|
-
def read_with_retry(session = nil, server_selector = nil, &block)
|
117
|
+
def read_with_retry(session = nil, server_selector = nil, context = nil, &block)
|
114
118
|
if session.nil? && server_selector.nil?
|
115
119
|
deprecated_legacy_read_with_retry(&block)
|
116
120
|
elsif session&.retry_reads?
|
117
|
-
modern_read_with_retry(session, server_selector, &block)
|
121
|
+
modern_read_with_retry(session, server_selector, context, &block)
|
118
122
|
elsif client.max_read_retries > 0
|
119
|
-
legacy_read_with_retry(session, server_selector, &block)
|
123
|
+
legacy_read_with_retry(session, server_selector, context, &block)
|
120
124
|
else
|
121
125
|
read_without_retry(session, server_selector, &block)
|
122
126
|
end
|
@@ -186,19 +190,26 @@ module Mongo
|
|
186
190
|
# being run on.
|
187
191
|
# @param [ Mongo::ServerSelector::Selectable ] server_selector Server
|
188
192
|
# selector for the operation.
|
193
|
+
# @param [ Mongo::Operation::Context ] context Context for the
|
194
|
+
# read operation.
|
189
195
|
# @param [ Proc ] block The block to execute.
|
190
196
|
#
|
191
197
|
# @return [ Result ] The result of the operation.
|
192
|
-
def modern_read_with_retry(session, server_selector, &block)
|
193
|
-
server = select_server(
|
198
|
+
def modern_read_with_retry(session, server_selector, context, &block)
|
199
|
+
server = select_server(
|
200
|
+
cluster,
|
201
|
+
server_selector,
|
202
|
+
session,
|
203
|
+
timeout: context&.remaining_timeout_sec
|
204
|
+
)
|
194
205
|
yield server
|
195
|
-
rescue *retryable_exceptions, Error::OperationFailure, Auth::Unauthorized, Error::PoolError => e
|
206
|
+
rescue *retryable_exceptions, Error::OperationFailure::Family, Auth::Unauthorized, Error::PoolError => e
|
196
207
|
e.add_notes('modern retry', 'attempt 1')
|
197
208
|
raise e if session.in_transaction?
|
198
209
|
raise e if !is_retryable_exception?(e) && !e.write_retryable?
|
199
|
-
retry_read(e, session, server_selector, failed_server: server, &block)
|
210
|
+
retry_read(e, session, server_selector, context: context, failed_server: server, &block)
|
200
211
|
end
|
201
|
-
|
212
|
+
|
202
213
|
# Attempts to do a "legacy" read with retry. The operation will be
|
203
214
|
# attempted multiple times, up to the client's `max_read_retries`
|
204
215
|
# setting.
|
@@ -207,23 +218,26 @@ module Mongo
|
|
207
218
|
# being run on.
|
208
219
|
# @param [ Mongo::ServerSelector::Selectable ] server_selector Server
|
209
220
|
# selector for the operation.
|
221
|
+
# @param [ Mongo::Operation::Context | nil ] context Context for the
|
222
|
+
# read operation.
|
210
223
|
# @param [ Proc ] block The block to execute.
|
211
224
|
#
|
212
225
|
# @return [ Result ] The result of the operation.
|
213
|
-
def legacy_read_with_retry(session, server_selector, &block)
|
226
|
+
def legacy_read_with_retry(session, server_selector, context = nil, &block)
|
227
|
+
context&.check_timeout!
|
214
228
|
attempt = attempt ? attempt + 1 : 1
|
215
229
|
yield select_server(cluster, server_selector, session)
|
216
|
-
rescue *
|
230
|
+
rescue *legacy_retryable_exceptions, Error::OperationFailure::Family => e
|
217
231
|
e.add_notes('legacy retry', "attempt #{attempt}")
|
218
|
-
|
219
|
-
if
|
232
|
+
|
233
|
+
if is_legacy_retryable_exception?(e)
|
220
234
|
raise e if attempt > client.max_read_retries || session&.in_transaction?
|
221
235
|
elsif e.retryable? && !session&.in_transaction?
|
222
236
|
raise e if attempt > client.max_read_retries
|
223
237
|
else
|
224
238
|
raise e
|
225
239
|
end
|
226
|
-
|
240
|
+
|
227
241
|
log_retry(e, message: 'Legacy read retry')
|
228
242
|
sleep(client.read_retry_interval) unless is_retryable_exception?(e)
|
229
243
|
retry
|
@@ -244,7 +258,7 @@ module Mongo
|
|
244
258
|
|
245
259
|
begin
|
246
260
|
yield server
|
247
|
-
rescue *retryable_exceptions, Error::PoolError, Error::OperationFailure => e
|
261
|
+
rescue *retryable_exceptions, Error::PoolError, Error::OperationFailure::Family => e
|
248
262
|
e.add_note('retries disabled')
|
249
263
|
raise e
|
250
264
|
end
|
@@ -258,40 +272,67 @@ module Mongo
|
|
258
272
|
# being run on.
|
259
273
|
# @param [ Mongo::ServerSelector::Selectable ] server_selector Server
|
260
274
|
# selector for the operation.
|
261
|
-
# @param [ Mongo::
|
275
|
+
# @param [ Mongo::Operation::Context | nil ] :context Context for the
|
276
|
+
# read operation.
|
277
|
+
# @param [ Mongo::Server | nil ] :failed_server The server on which the original
|
262
278
|
# operation failed.
|
263
279
|
# @param [ Proc ] block The block to execute.
|
264
|
-
#
|
280
|
+
#
|
265
281
|
# @return [ Result ] The result of the operation.
|
266
|
-
def retry_read(original_error, session, server_selector, failed_server: nil, &block)
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
raise original_error
|
272
|
-
end
|
273
|
-
|
282
|
+
def retry_read(original_error, session, server_selector, context: nil, failed_server: nil, &block)
|
283
|
+
server = select_server_for_retry(
|
284
|
+
original_error, session, server_selector, context, failed_server
|
285
|
+
)
|
286
|
+
|
274
287
|
log_retry(original_error, message: 'Read retry')
|
275
|
-
|
288
|
+
|
276
289
|
begin
|
290
|
+
context&.check_timeout!
|
291
|
+
attempt = attempt ? attempt + 1 : 2
|
277
292
|
yield server, true
|
293
|
+
rescue Error::TimeoutError
|
294
|
+
raise
|
278
295
|
rescue *retryable_exceptions => e
|
279
|
-
e.add_notes('modern retry',
|
280
|
-
|
281
|
-
|
296
|
+
e.add_notes('modern retry', "attempt #{attempt}")
|
297
|
+
if context&.csot?
|
298
|
+
failed_server = server
|
299
|
+
retry
|
300
|
+
else
|
301
|
+
raise e
|
302
|
+
end
|
303
|
+
rescue Error::OperationFailure::Family, Error::PoolError => e
|
282
304
|
e.add_note('modern retry')
|
283
|
-
|
305
|
+
if e.write_retryable?
|
306
|
+
e.add_note("attempt #{attempt}")
|
307
|
+
if context&.csot?
|
308
|
+
failed_server = server
|
309
|
+
retry
|
310
|
+
else
|
311
|
+
raise e
|
312
|
+
end
|
313
|
+
else
|
284
314
|
original_error.add_note("later retry failed: #{e.class}: #{e}")
|
285
315
|
raise original_error
|
286
316
|
end
|
287
|
-
e.add_note("attempt 2")
|
288
|
-
raise e
|
289
317
|
rescue Error, Error::AuthError => e
|
290
318
|
e.add_note('modern retry')
|
291
319
|
original_error.add_note("later retry failed: #{e.class}: #{e}")
|
292
320
|
raise original_error
|
293
321
|
end
|
294
322
|
end
|
323
|
+
|
324
|
+
def select_server_for_retry(original_error, session, server_selector, context, failed_server)
|
325
|
+
select_server(
|
326
|
+
cluster,
|
327
|
+
server_selector,
|
328
|
+
session,
|
329
|
+
failed_server,
|
330
|
+
timeout: context&.remaining_timeout_sec
|
331
|
+
)
|
332
|
+
rescue Error, Error::AuthError => e
|
333
|
+
original_error.add_note("later retry failed: #{e.class}: #{e}")
|
334
|
+
raise original_error
|
335
|
+
end
|
295
336
|
end
|
296
337
|
end
|
297
338
|
end
|
@@ -74,7 +74,11 @@ module Mongo
|
|
74
74
|
# If we are here, session is not nil. A session being nil would have
|
75
75
|
# failed retry_write_allowed? check.
|
76
76
|
|
77
|
-
server = select_server(
|
77
|
+
server = select_server(
|
78
|
+
cluster, ServerSelector.primary,
|
79
|
+
session,
|
80
|
+
timeout: context.remaining_timeout_sec
|
81
|
+
)
|
78
82
|
|
79
83
|
unless ending_transaction || server.retry_writes?
|
80
84
|
return legacy_write_with_retry(server, context: context, &block)
|
@@ -104,13 +108,13 @@ module Mongo
|
|
104
108
|
session = context.session
|
105
109
|
server = select_server(cluster, ServerSelector.primary, session)
|
106
110
|
options = session&.client&.options || {}
|
107
|
-
|
111
|
+
|
108
112
|
if options[:retry_writes]
|
109
113
|
begin
|
110
114
|
server.with_connection(connection_global_id: context.connection_global_id) do |connection|
|
111
115
|
yield connection, nil, context
|
112
116
|
end
|
113
|
-
rescue *retryable_exceptions, Error::PoolError, Error::OperationFailure => e
|
117
|
+
rescue *retryable_exceptions, Error::PoolError, Error::OperationFailure::Family => e
|
114
118
|
e.add_note('retries disabled')
|
115
119
|
raise e
|
116
120
|
end
|
@@ -170,6 +174,7 @@ module Mongo
|
|
170
174
|
# @api private
|
171
175
|
def legacy_write_with_retry(server = nil, context:)
|
172
176
|
session = context.session
|
177
|
+
context.check_timeout!
|
173
178
|
|
174
179
|
# This is the pre-session retry logic, and is not subject to
|
175
180
|
# current retryable write specifications.
|
@@ -177,12 +182,20 @@ module Mongo
|
|
177
182
|
attempt = 0
|
178
183
|
begin
|
179
184
|
attempt += 1
|
180
|
-
server ||= select_server(
|
181
|
-
|
185
|
+
server ||= select_server(
|
186
|
+
cluster,
|
187
|
+
ServerSelector.primary,
|
188
|
+
session,
|
189
|
+
timeout: context.remaining_timeout_sec
|
190
|
+
)
|
191
|
+
server.with_connection(
|
192
|
+
connection_global_id: context.connection_global_id,
|
193
|
+
context: context
|
194
|
+
) do |connection|
|
182
195
|
# Legacy retries do not use txn_num
|
183
196
|
yield connection, nil, context.dup
|
184
197
|
end
|
185
|
-
rescue Error::OperationFailure => e
|
198
|
+
rescue Error::OperationFailure::Family => e
|
186
199
|
e.add_note('legacy retry')
|
187
200
|
e.add_note("attempt #{attempt}")
|
188
201
|
server = nil
|
@@ -219,8 +232,11 @@ module Mongo
|
|
219
232
|
def modern_write_with_retry(session, server, context, &block)
|
220
233
|
txn_num = nil
|
221
234
|
connection_succeeded = false
|
222
|
-
|
223
|
-
server.with_connection(
|
235
|
+
|
236
|
+
server.with_connection(
|
237
|
+
connection_global_id: context.connection_global_id,
|
238
|
+
context: context
|
239
|
+
) do |connection|
|
224
240
|
connection_succeeded = true
|
225
241
|
|
226
242
|
session.materialize_if_needed
|
@@ -230,10 +246,10 @@ module Mongo
|
|
230
246
|
# it later for the retry as well.
|
231
247
|
yield connection, txn_num, context.dup
|
232
248
|
end
|
233
|
-
rescue *retryable_exceptions, Error::PoolError, Auth::Unauthorized, Error::OperationFailure => e
|
249
|
+
rescue *retryable_exceptions, Error::PoolError, Auth::Unauthorized, Error::OperationFailure::Family => e
|
234
250
|
e.add_notes('modern retry', 'attempt 1')
|
235
251
|
|
236
|
-
if e.is_a?(Error::OperationFailure)
|
252
|
+
if e.is_a?(Error::OperationFailure::Family)
|
237
253
|
ensure_retryable!(e)
|
238
254
|
else
|
239
255
|
ensure_labeled_retryable!(e, connection_succeeded, session)
|
@@ -256,6 +272,8 @@ module Mongo
|
|
256
272
|
#
|
257
273
|
# @return [ Result ] The result of the operation.
|
258
274
|
def retry_write(original_error, txn_num, context:, failed_server: nil, &block)
|
275
|
+
context&.check_timeout!
|
276
|
+
|
259
277
|
session = context.session
|
260
278
|
|
261
279
|
# We do not request a scan of the cluster here, because error handling
|
@@ -263,8 +281,14 @@ module Mongo
|
|
263
281
|
# server description and/or topology as necessary (specifically,
|
264
282
|
# a socket error or a not master error should have marked the respective
|
265
283
|
# server unknown). Here we just need to wait for server selection.
|
266
|
-
server = select_server(
|
267
|
-
|
284
|
+
server = select_server(
|
285
|
+
cluster,
|
286
|
+
ServerSelector.primary,
|
287
|
+
session,
|
288
|
+
failed_server,
|
289
|
+
timeout: context.remaining_timeout_sec
|
290
|
+
)
|
291
|
+
|
268
292
|
unless server.retry_writes?
|
269
293
|
# Do not need to add "modern retry" here, it should already be on
|
270
294
|
# the first exception.
|
@@ -278,15 +302,22 @@ module Mongo
|
|
278
302
|
# special marker class to bypass the ordinarily applicable rescues.
|
279
303
|
raise Error::RaiseOriginalError
|
280
304
|
end
|
281
|
-
|
305
|
+
|
306
|
+
attempt = attempt ? attempt + 1 : 2
|
282
307
|
log_retry(original_error, message: 'Write retry')
|
283
308
|
server.with_connection(connection_global_id: context.connection_global_id) do |connection|
|
284
309
|
yield(connection, txn_num, context)
|
285
310
|
end
|
286
311
|
rescue *retryable_exceptions, Error::PoolError => e
|
287
|
-
|
288
|
-
|
289
|
-
|
312
|
+
maybe_fail_on_retryable(e, original_error, context, attempt)
|
313
|
+
failed_server = server
|
314
|
+
retry
|
315
|
+
rescue Error::OperationFailure::Family => e
|
316
|
+
maybe_fail_on_operation_failure(e, original_error, context, attempt)
|
317
|
+
failed_server = server
|
318
|
+
retry
|
319
|
+
rescue Mongo::Error::TimeoutError
|
320
|
+
raise
|
290
321
|
rescue Error, Error::AuthError => e
|
291
322
|
fail_on_other_error!(e, original_error)
|
292
323
|
rescue Error::RaiseOriginalError
|
@@ -332,10 +363,10 @@ module Mongo
|
|
332
363
|
|
333
364
|
# Raise either e, or original_error, depending on whether e is
|
334
365
|
# write_retryable.
|
335
|
-
def
|
366
|
+
def maybe_fail_on_retryable(e, original_error, context, attempt)
|
336
367
|
if e.write_retryable?
|
337
|
-
e.add_notes('modern retry',
|
338
|
-
raise e
|
368
|
+
e.add_notes('modern retry', "attempt #{attempt}")
|
369
|
+
raise e unless context&.deadline
|
339
370
|
else
|
340
371
|
original_error.add_note("later retry failed: #{e.class}: #{e}")
|
341
372
|
raise original_error
|
@@ -344,11 +375,11 @@ module Mongo
|
|
344
375
|
|
345
376
|
# Raise either e, or original_error, depending on whether e is
|
346
377
|
# appropriately labeled.
|
347
|
-
def
|
378
|
+
def maybe_fail_on_operation_failure(e, original_error, context, attempt)
|
348
379
|
e.add_note('modern retry')
|
349
380
|
if e.label?('RetryableWriteError') && !e.label?('NoWritesPerformed')
|
350
|
-
e.add_note(
|
351
|
-
raise e
|
381
|
+
e.add_note("attempt #{attempt}")
|
382
|
+
raise e unless context&.deadline
|
352
383
|
else
|
353
384
|
original_error.add_note("later retry failed: #{e.class}: #{e}")
|
354
385
|
raise original_error
|
data/lib/mongo/retryable.rb
CHANGED
@@ -46,8 +46,14 @@ module Mongo
|
|
46
46
|
# @api private
|
47
47
|
#
|
48
48
|
# @return [ Mongo::Server ] A server matching the server preference.
|
49
|
-
def select_server(cluster, server_selector, session, failed_server = nil)
|
50
|
-
server_selector.select_server(
|
49
|
+
def select_server(cluster, server_selector, session, failed_server = nil, timeout: nil)
|
50
|
+
server_selector.select_server(
|
51
|
+
cluster,
|
52
|
+
nil,
|
53
|
+
session,
|
54
|
+
deprioritized: [failed_server].compact,
|
55
|
+
timeout: timeout
|
56
|
+
)
|
51
57
|
end
|
52
58
|
|
53
59
|
# Returns the read worker for handling retryable reads.
|
@@ -226,11 +226,11 @@ module Mongo
|
|
226
226
|
# @return [ true ] If the connection succeeded.
|
227
227
|
#
|
228
228
|
# @since 2.0.0
|
229
|
-
def connect!
|
229
|
+
def connect!(context = nil)
|
230
230
|
raise_if_closed!
|
231
231
|
|
232
232
|
unless @socket
|
233
|
-
@socket = create_socket
|
233
|
+
@socket = create_socket(context)
|
234
234
|
@description, @compressor = do_connect
|
235
235
|
|
236
236
|
if server.load_balancer?
|
@@ -256,10 +256,16 @@ module Mongo
|
|
256
256
|
#
|
257
257
|
#
|
258
258
|
# @return [ Socket ] The created socket.
|
259
|
-
private def create_socket
|
259
|
+
private def create_socket(context = nil)
|
260
260
|
add_server_diagnostics do
|
261
|
-
|
262
|
-
connection_address: address,
|
261
|
+
opts = ssl_options.merge(
|
262
|
+
connection_address: address,
|
263
|
+
connection_generation: generation,
|
264
|
+
pipe: options[:pipe],
|
265
|
+
connect_timeout: context&.remaining_timeout_sec,
|
266
|
+
csot: !!context&.csot?
|
267
|
+
)
|
268
|
+
address.socket(socket_timeout, opts)
|
263
269
|
end
|
264
270
|
end
|
265
271
|
|