mongo 2.23.0 → 2.24.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/bin/mongo_console +0 -1
- data/lib/mongo/active_support.rb +1 -2
- data/lib/mongo/address/ipv4.rb +3 -6
- data/lib/mongo/address/ipv6.rb +6 -10
- data/lib/mongo/address/unix.rb +1 -4
- data/lib/mongo/address/validator.rb +16 -28
- data/lib/mongo/address.rb +30 -40
- data/lib/mongo/auth/aws/conversation.rb +6 -10
- data/lib/mongo/auth/aws/credentials.rb +0 -1
- data/lib/mongo/auth/aws/credentials_cache.rb +0 -1
- data/lib/mongo/auth/aws/credentials_retriever.rb +45 -59
- data/lib/mongo/auth/aws/request.rb +20 -35
- data/lib/mongo/auth/aws.rb +1 -2
- data/lib/mongo/auth/base.rb +20 -29
- data/lib/mongo/auth/conversation_base.rb +14 -18
- data/lib/mongo/auth/cr/conversation.rb +0 -3
- data/lib/mongo/auth/cr.rb +1 -4
- data/lib/mongo/auth/credential_cache.rb +0 -2
- data/lib/mongo/auth/gssapi/conversation.rb +3 -8
- data/lib/mongo/auth/gssapi.rb +1 -4
- data/lib/mongo/auth/ldap/conversation.rb +0 -3
- data/lib/mongo/auth/ldap.rb +1 -4
- data/lib/mongo/auth/roles.rb +16 -19
- data/lib/mongo/auth/sasl_conversation_base.rb +7 -11
- data/lib/mongo/auth/scram/conversation.rb +2 -5
- data/lib/mongo/auth/scram.rb +5 -10
- data/lib/mongo/auth/scram256/conversation.rb +2 -5
- data/lib/mongo/auth/scram256.rb +1 -3
- data/lib/mongo/auth/scram_conversation_base.rb +18 -24
- data/lib/mongo/auth/stringprep/profiles/sasl.rb +17 -18
- data/lib/mongo/auth/stringprep/tables.rb +2209 -2210
- data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +36 -38
- data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +1142 -1150
- data/lib/mongo/auth/stringprep.rb +9 -12
- data/lib/mongo/auth/user/view.rb +3 -5
- data/lib/mongo/auth/user.rb +14 -24
- data/lib/mongo/auth/x509/conversation.rb +0 -3
- data/lib/mongo/auth/x509.rb +7 -9
- data/lib/mongo/auth.rb +18 -30
- data/lib/mongo/background_thread.rb +9 -17
- data/lib/mongo/bson.rb +0 -2
- data/lib/mongo/bulk_write/combineable.rb +0 -3
- data/lib/mongo/bulk_write/ordered_combiner.rb +1 -3
- data/lib/mongo/bulk_write/result.rb +11 -16
- data/lib/mongo/bulk_write/result_combiner.rb +9 -12
- data/lib/mongo/bulk_write/transformable.rb +16 -19
- data/lib/mongo/bulk_write/unordered_combiner.rb +1 -3
- data/lib/mongo/bulk_write/validatable.rb +11 -18
- data/lib/mongo/bulk_write.rb +76 -91
- data/lib/mongo/caching_cursor.rb +2 -7
- data/lib/mongo/client.rb +230 -275
- data/lib/mongo/client_encryption.rb +4 -5
- data/lib/mongo/cluster/periodic_executor.rb +2 -5
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +21 -29
- data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -6
- data/lib/mongo/cluster/sdam_flow.rb +136 -159
- data/lib/mongo/cluster/topology/base.rb +15 -18
- data/lib/mongo/cluster/topology/load_balanced.rb +24 -14
- data/lib/mongo/cluster/topology/no_replica_set_options.rb +3 -6
- data/lib/mongo/cluster/topology/replica_set_no_primary.rb +20 -23
- data/lib/mongo/cluster/topology/replica_set_with_primary.rb +0 -2
- data/lib/mongo/cluster/topology/sharded.rb +19 -9
- data/lib/mongo/cluster/topology/single.rb +24 -14
- data/lib/mongo/cluster/topology/unknown.rb +20 -10
- data/lib/mongo/cluster/topology.rb +29 -25
- data/lib/mongo/cluster.rb +148 -183
- data/lib/mongo/cluster_time.rb +14 -31
- data/lib/mongo/collection/helpers.rb +5 -8
- data/lib/mongo/collection/view/aggregation.rb +5 -10
- data/lib/mongo/collection/view/builder/aggregation.rb +6 -9
- data/lib/mongo/collection/view/builder/map_reduce.rb +18 -17
- data/lib/mongo/collection/view/builder.rb +0 -1
- data/lib/mongo/collection/view/change_stream/retryable.rb +3 -8
- data/lib/mongo/collection/view/change_stream.rb +59 -58
- data/lib/mongo/collection/view/explainable.rb +11 -20
- data/lib/mongo/collection/view/immutable.rb +1 -3
- data/lib/mongo/collection/view/iterable.rb +35 -28
- data/lib/mongo/collection/view/map_reduce.rb +20 -25
- data/lib/mongo/collection/view/readable.rb +50 -57
- data/lib/mongo/collection/view/writable.rb +56 -72
- data/lib/mongo/collection/view.rb +9 -8
- data/lib/mongo/collection.rb +63 -76
- data/lib/mongo/condition_variable.rb +4 -4
- data/lib/mongo/config/options.rb +0 -3
- data/lib/mongo/config/validators/option.rb +3 -5
- data/lib/mongo/config.rb +2 -4
- data/lib/mongo/crypt/auto_decryption_context.rb +0 -3
- data/lib/mongo/crypt/auto_encrypter.rb +34 -43
- data/lib/mongo/crypt/auto_encryption_context.rb +0 -3
- data/lib/mongo/crypt/binary.rb +5 -9
- data/lib/mongo/crypt/binding.rb +149 -155
- data/lib/mongo/crypt/context.rb +10 -17
- data/lib/mongo/crypt/data_key_context.rb +2 -7
- data/lib/mongo/crypt/encryption_io.rb +29 -39
- data/lib/mongo/crypt/explicit_decryption_context.rb +0 -3
- data/lib/mongo/crypt/explicit_encrypter.rb +1 -1
- data/lib/mongo/crypt/explicit_encryption_context.rb +19 -30
- data/lib/mongo/crypt/explicit_encryption_expression_context.rb +0 -2
- data/lib/mongo/crypt/handle.rb +42 -48
- data/lib/mongo/crypt/hooks.rb +12 -15
- data/lib/mongo/crypt/kms/aws/credentials.rb +12 -16
- data/lib/mongo/crypt/kms/aws/master_document.rb +6 -9
- data/lib/mongo/crypt/kms/aws.rb +0 -2
- data/lib/mongo/crypt/kms/azure/credentials_retriever.rb +2 -7
- data/lib/mongo/crypt/kms/azure/master_document.rb +15 -19
- data/lib/mongo/crypt/kms/azure.rb +0 -1
- data/lib/mongo/crypt/kms/credentials.rb +13 -27
- data/lib/mongo/crypt/kms/gcp/credentials.rb +12 -14
- data/lib/mongo/crypt/kms/gcp/credentials_retriever.rb +7 -9
- data/lib/mongo/crypt/kms/gcp/master_document.rb +12 -16
- data/lib/mongo/crypt/kms/gcp.rb +0 -2
- data/lib/mongo/crypt/kms/kmip/credentials.rb +7 -8
- data/lib/mongo/crypt/kms/kmip/master_document.rb +3 -5
- data/lib/mongo/crypt/kms/kmip.rb +0 -1
- data/lib/mongo/crypt/kms/local/credentials.rb +7 -8
- data/lib/mongo/crypt/kms/local/master_document.rb +2 -6
- data/lib/mongo/crypt/kms/local.rb +0 -1
- data/lib/mongo/crypt/kms/master_key_document.rb +11 -15
- data/lib/mongo/crypt/kms.rb +14 -16
- data/lib/mongo/crypt/kms_context.rb +0 -2
- data/lib/mongo/crypt/rewrap_many_data_key_context.rb +2 -7
- data/lib/mongo/crypt/rewrap_many_data_key_result.rb +2 -4
- data/lib/mongo/crypt/status.rb +12 -14
- data/lib/mongo/crypt.rb +0 -1
- data/lib/mongo/csot_timeout_holder.rb +3 -2
- data/lib/mongo/cursor/kill_spec.rb +7 -10
- data/lib/mongo/cursor.rb +74 -64
- data/lib/mongo/cursor_host.rb +8 -10
- data/lib/mongo/database/view.rb +16 -37
- data/lib/mongo/database.rb +52 -56
- data/lib/mongo/dbref.rb +0 -1
- data/lib/mongo/distinguishing_semaphore.rb +0 -1
- data/lib/mongo/error/auth_error.rb +0 -2
- data/lib/mongo/error/bad_load_balancer_target.rb +0 -2
- data/lib/mongo/error/bulk_write_error.rb +7 -10
- data/lib/mongo/error/change_stream_resumable.rb +0 -2
- data/lib/mongo/error/client_closed.rb +0 -2
- data/lib/mongo/error/closed_stream.rb +1 -4
- data/lib/mongo/error/connection_check_out_timeout.rb +3 -6
- data/lib/mongo/error/connection_perished.rb +0 -2
- data/lib/mongo/error/connection_unavailable.rb +0 -2
- data/lib/mongo/error/credential_check_error.rb +0 -2
- data/lib/mongo/error/crypt_error.rb +0 -2
- data/lib/mongo/error/extra_file_chunk.rb +1 -4
- data/lib/mongo/error/failed_string_prep_validation.rb +5 -6
- data/lib/mongo/error/file_not_found.rb +0 -3
- data/lib/mongo/error/handshake_error.rb +0 -2
- data/lib/mongo/error/insufficient_iteration_count.rb +1 -4
- data/lib/mongo/error/internal_driver_error.rb +0 -2
- data/lib/mongo/error/invalid_address.rb +0 -2
- data/lib/mongo/error/invalid_application_name.rb +0 -3
- data/lib/mongo/error/invalid_bulk_operation.rb +1 -4
- data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -4
- data/lib/mongo/error/invalid_collection_name.rb +1 -4
- data/lib/mongo/error/invalid_config_option.rb +0 -3
- data/lib/mongo/error/invalid_cursor_operation.rb +0 -2
- data/lib/mongo/error/invalid_database_name.rb +1 -4
- data/lib/mongo/error/invalid_document.rb +1 -4
- data/lib/mongo/error/invalid_file.rb +0 -3
- data/lib/mongo/error/invalid_file_revision.rb +0 -3
- data/lib/mongo/error/invalid_min_pool_size.rb +0 -3
- data/lib/mongo/error/invalid_nonce.rb +0 -3
- data/lib/mongo/error/invalid_read_concern.rb +2 -4
- data/lib/mongo/error/invalid_read_option.rb +0 -3
- data/lib/mongo/error/invalid_replacement_document.rb +2 -5
- data/lib/mongo/error/invalid_server_auth_host.rb +0 -2
- data/lib/mongo/error/invalid_server_auth_response.rb +0 -2
- data/lib/mongo/error/invalid_server_preference.rb +7 -16
- data/lib/mongo/error/invalid_session.rb +1 -4
- data/lib/mongo/error/invalid_signature.rb +0 -3
- data/lib/mongo/error/invalid_transaction_operation.rb +5 -8
- data/lib/mongo/error/invalid_txt_record.rb +0 -2
- data/lib/mongo/error/invalid_update_document.rb +2 -5
- data/lib/mongo/error/invalid_uri.rb +1 -4
- data/lib/mongo/error/invalid_write_concern.rb +2 -5
- data/lib/mongo/error/kms_error.rb +0 -2
- data/lib/mongo/error/labelable.rb +0 -3
- data/lib/mongo/error/lint_error.rb +0 -2
- data/lib/mongo/error/max_bson_size.rb +8 -11
- data/lib/mongo/error/max_message_size.rb +2 -5
- data/lib/mongo/error/mismatched_domain.rb +0 -2
- data/lib/mongo/error/missing_connection.rb +0 -2
- data/lib/mongo/error/missing_file_chunk.rb +0 -3
- data/lib/mongo/error/missing_password.rb +0 -2
- data/lib/mongo/error/missing_resume_token.rb +1 -4
- data/lib/mongo/error/missing_scram_server_signature.rb +2 -4
- data/lib/mongo/error/missing_service_id.rb +0 -2
- data/lib/mongo/error/mongocryptd_spawn_error.rb +0 -2
- data/lib/mongo/error/multi_index_drop.rb +0 -3
- data/lib/mongo/error/need_primary_server.rb +0 -2
- data/lib/mongo/error/no_server_available.rb +3 -8
- data/lib/mongo/error/no_service_connection_available.rb +1 -3
- data/lib/mongo/error/no_srv_records.rb +0 -2
- data/lib/mongo/error/notable.rb +8 -16
- data/lib/mongo/error/operation_failure.rb +22 -35
- data/lib/mongo/error/parser.rb +33 -75
- data/lib/mongo/error/pool_cleared_error.rb +1 -3
- data/lib/mongo/error/pool_closed_error.rb +0 -3
- data/lib/mongo/error/pool_error.rb +0 -3
- data/lib/mongo/error/pool_paused_error.rb +0 -2
- data/lib/mongo/error/raise_original_error.rb +1 -3
- data/lib/mongo/error/read_write_retryable.rb +14 -17
- data/lib/mongo/error/sdam_error_detection.rb +3 -5
- data/lib/mongo/error/server_api_conflict.rb +0 -2
- data/lib/mongo/error/server_certificate_revoked.rb +0 -2
- data/lib/mongo/error/server_not_usable.rb +0 -2
- data/lib/mongo/error/session_ended.rb +1 -3
- data/lib/mongo/error/session_not_materialized.rb +1 -3
- data/lib/mongo/error/sessions_not_supported.rb +1 -4
- data/lib/mongo/error/snapshot_session_invalid_server_version.rb +1 -4
- data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +1 -4
- data/lib/mongo/error/socket_error.rb +0 -2
- data/lib/mongo/error/socket_timeout_error.rb +0 -2
- data/lib/mongo/error/transactions_not_supported.rb +3 -6
- data/lib/mongo/error/unchangeable_collection_option.rb +1 -4
- data/lib/mongo/error/unexpected_chunk_length.rb +0 -3
- data/lib/mongo/error/unexpected_response.rb +1 -4
- data/lib/mongo/error/unknown_payload_type.rb +0 -3
- data/lib/mongo/error/unmet_dependency.rb +0 -2
- data/lib/mongo/error/unsupported_array_filters.rb +3 -24
- data/lib/mongo/error/unsupported_collation.rb +3 -24
- data/lib/mongo/error/unsupported_features.rb +0 -2
- data/lib/mongo/error/unsupported_message_type.rb +0 -2
- data/lib/mongo/error/unsupported_option.rb +19 -21
- data/lib/mongo/error/write_retryable.rb +0 -2
- data/lib/mongo/error.rb +10 -24
- data/lib/mongo/event/base.rb +0 -2
- data/lib/mongo/event/listeners.rb +0 -3
- data/lib/mongo/event/publisher.rb +0 -3
- data/lib/mongo/event/subscriber.rb +0 -4
- data/lib/mongo/event.rb +4 -6
- data/lib/mongo/grid/file/chunk.rb +7 -10
- data/lib/mongo/grid/file/info.rb +20 -24
- data/lib/mongo/grid/file.rb +7 -8
- data/lib/mongo/grid/fs_bucket.rb +40 -48
- data/lib/mongo/grid/stream/read.rb +25 -35
- data/lib/mongo/grid/stream/write.rb +17 -22
- data/lib/mongo/grid/stream.rb +2 -4
- data/lib/mongo/grid.rb +0 -1
- data/lib/mongo/id.rb +0 -1
- data/lib/mongo/index/view.rb +49 -48
- data/lib/mongo/index.rb +7 -10
- data/lib/mongo/lint.rb +31 -37
- data/lib/mongo/loggable.rb +5 -8
- data/lib/mongo/logger.rb +1 -7
- data/lib/mongo/monitoring/cmap_log_subscriber.rb +0 -2
- data/lib/mongo/monitoring/command_log_subscriber.rb +25 -33
- data/lib/mongo/monitoring/event/cmap/base.rb +0 -2
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +0 -3
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +2 -5
- data/lib/mongo/monitoring/event/cmap/connection_closed.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/connection_created.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/connection_ready.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +0 -3
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +1 -4
- data/lib/mongo/monitoring/event/cmap/pool_ready.rb +1 -4
- data/lib/mongo/monitoring/event/cmap.rb +0 -1
- data/lib/mongo/monitoring/event/command_failed.rb +5 -9
- data/lib/mongo/monitoring/event/command_started.rb +8 -12
- data/lib/mongo/monitoring/event/command_succeeded.rb +7 -15
- data/lib/mongo/monitoring/event/secure.rb +15 -20
- data/lib/mongo/monitoring/event/server_closed.rb +1 -4
- data/lib/mongo/monitoring/event/server_description_changed.rb +4 -8
- data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +5 -10
- data/lib/mongo/monitoring/event/server_heartbeat_started.rb +1 -4
- data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +3 -8
- data/lib/mongo/monitoring/event/server_opening.rb +1 -4
- data/lib/mongo/monitoring/event/topology_changed.rb +2 -5
- data/lib/mongo/monitoring/event/topology_closed.rb +1 -4
- data/lib/mongo/monitoring/event/topology_opening.rb +1 -4
- data/lib/mongo/monitoring/event.rb +0 -1
- data/lib/mongo/monitoring/publishable.rb +20 -30
- data/lib/mongo/monitoring/sdam_log_subscriber.rb +0 -2
- data/lib/mongo/monitoring/server_closed_log_subscriber.rb +0 -3
- data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +0 -3
- data/lib/mongo/monitoring/server_opening_log_subscriber.rb +0 -3
- data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +5 -8
- data/lib/mongo/monitoring/topology_closed_log_subscriber.rb +0 -3
- data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +0 -3
- data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +1 -3
- data/lib/mongo/monitoring.rb +38 -39
- data/lib/mongo/operation/aggregate/op_msg.rb +0 -2
- data/lib/mongo/operation/aggregate/result.rb +3 -6
- data/lib/mongo/operation/aggregate.rb +0 -2
- data/lib/mongo/operation/collections_info/result.rb +0 -3
- data/lib/mongo/operation/collections_info.rb +0 -2
- data/lib/mongo/operation/command/op_msg.rb +1 -4
- data/lib/mongo/operation/command.rb +0 -2
- data/lib/mongo/operation/context.rb +13 -16
- data/lib/mongo/operation/count/op_msg.rb +2 -4
- data/lib/mongo/operation/count.rb +0 -2
- data/lib/mongo/operation/create/op_msg.rb +2 -5
- data/lib/mongo/operation/create.rb +0 -2
- data/lib/mongo/operation/create_index/op_msg.rb +3 -7
- data/lib/mongo/operation/create_index.rb +0 -2
- data/lib/mongo/operation/create_user/op_msg.rb +2 -4
- data/lib/mongo/operation/create_user.rb +0 -2
- data/lib/mongo/operation/delete/bulk_result.rb +2 -3
- data/lib/mongo/operation/delete/op_msg.rb +3 -10
- data/lib/mongo/operation/delete/result.rb +0 -3
- data/lib/mongo/operation/delete.rb +1 -5
- data/lib/mongo/operation/distinct/op_msg.rb +2 -5
- data/lib/mongo/operation/distinct.rb +0 -2
- data/lib/mongo/operation/drop/op_msg.rb +0 -2
- data/lib/mongo/operation/drop.rb +0 -2
- data/lib/mongo/operation/drop_database/op_msg.rb +0 -2
- data/lib/mongo/operation/drop_database.rb +0 -2
- data/lib/mongo/operation/drop_index/op_msg.rb +4 -6
- data/lib/mongo/operation/drop_index.rb +0 -2
- data/lib/mongo/operation/explain/op_msg.rb +0 -2
- data/lib/mongo/operation/explain/result.rb +0 -3
- data/lib/mongo/operation/explain.rb +0 -2
- data/lib/mongo/operation/find/builder/command.rb +4 -12
- data/lib/mongo/operation/find/builder/flags.rb +9 -15
- data/lib/mongo/operation/find/builder/modifiers.rb +1 -4
- data/lib/mongo/operation/find/builder.rb +0 -1
- data/lib/mongo/operation/find/op_msg.rb +4 -12
- data/lib/mongo/operation/find/result.rb +0 -3
- data/lib/mongo/operation/find.rb +0 -2
- data/lib/mongo/operation/get_more/command_builder.rb +1 -6
- data/lib/mongo/operation/get_more/op_msg.rb +10 -4
- data/lib/mongo/operation/get_more/result.rb +0 -3
- data/lib/mongo/operation/get_more.rb +0 -2
- data/lib/mongo/operation/indexes/op_msg.rb +0 -2
- data/lib/mongo/operation/indexes/result.rb +1 -5
- data/lib/mongo/operation/indexes.rb +0 -2
- data/lib/mongo/operation/insert/bulk_result.rb +2 -6
- data/lib/mongo/operation/insert/op_msg.rb +2 -4
- data/lib/mongo/operation/insert/result.rb +0 -3
- data/lib/mongo/operation/insert.rb +2 -5
- data/lib/mongo/operation/kill_cursors/command_builder.rb +0 -3
- data/lib/mongo/operation/kill_cursors/op_msg.rb +1 -3
- data/lib/mongo/operation/kill_cursors.rb +0 -2
- data/lib/mongo/operation/list_collections/op_msg.rb +4 -6
- data/lib/mongo/operation/list_collections/result.rb +1 -4
- data/lib/mongo/operation/list_collections.rb +0 -2
- data/lib/mongo/operation/map_reduce/op_msg.rb +0 -2
- data/lib/mongo/operation/map_reduce/result.rb +3 -6
- data/lib/mongo/operation/map_reduce.rb +0 -2
- data/lib/mongo/operation/op_msg_base.rb +0 -1
- data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -5
- data/lib/mongo/operation/parallel_scan/result.rb +2 -5
- data/lib/mongo/operation/parallel_scan.rb +0 -2
- data/lib/mongo/operation/remove_user/op_msg.rb +2 -4
- data/lib/mongo/operation/remove_user.rb +0 -2
- data/lib/mongo/operation/result.rb +38 -48
- data/lib/mongo/operation/shared/bypass_document_validation.rb +3 -7
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +0 -3
- data/lib/mongo/operation/shared/executable.rb +19 -28
- data/lib/mongo/operation/shared/executable_no_validate.rb +0 -3
- data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -2
- data/lib/mongo/operation/shared/idable.rb +3 -6
- data/lib/mongo/operation/shared/limited.rb +0 -3
- data/lib/mongo/operation/shared/object_id_generator.rb +0 -3
- data/lib/mongo/operation/shared/op_msg_executable.rb +0 -2
- data/lib/mongo/operation/shared/polymorphic_lookup.rb +0 -2
- data/lib/mongo/operation/shared/polymorphic_result.rb +2 -4
- data/lib/mongo/operation/shared/read_preference_supported.rb +10 -15
- data/lib/mongo/operation/shared/response_handling.rb +13 -26
- data/lib/mongo/operation/shared/result/aggregatable.rb +12 -13
- data/lib/mongo/operation/shared/sessions_supported.rb +87 -99
- data/lib/mongo/operation/shared/specifiable.rb +32 -58
- data/lib/mongo/operation/shared/write.rb +12 -17
- data/lib/mongo/operation/shared/write_concern_supported.rb +4 -7
- data/lib/mongo/operation/update/bulk_result.rb +13 -17
- data/lib/mongo/operation/update/op_msg.rb +2 -5
- data/lib/mongo/operation/update/result.rb +5 -5
- data/lib/mongo/operation/update.rb +1 -5
- data/lib/mongo/operation/update_user/op_msg.rb +2 -4
- data/lib/mongo/operation/update_user.rb +0 -2
- data/lib/mongo/operation/users_info/op_msg.rb +2 -4
- data/lib/mongo/operation/users_info/result.rb +1 -4
- data/lib/mongo/operation/users_info.rb +0 -2
- data/lib/mongo/operation/write_command/op_msg.rb +2 -10
- data/lib/mongo/operation/write_command.rb +0 -2
- data/lib/mongo/operation.rb +9 -14
- data/lib/mongo/options/mapper.rb +8 -15
- data/lib/mongo/options/redacted.rb +7 -9
- data/lib/mongo/options.rb +0 -1
- data/lib/mongo/protocol/bit_vector.rb +3 -5
- data/lib/mongo/protocol/caching_hash.rb +2 -7
- data/lib/mongo/protocol/compressed.rb +5 -10
- data/lib/mongo/protocol/get_more.rb +2 -8
- data/lib/mongo/protocol/kill_cursors.rb +2 -8
- data/lib/mongo/protocol/message.rb +103 -105
- data/lib/mongo/protocol/msg.rb +48 -63
- data/lib/mongo/protocol/query.rb +32 -41
- data/lib/mongo/protocol/registry.rb +2 -5
- data/lib/mongo/protocol/reply.rb +10 -16
- data/lib/mongo/protocol/serializers.rb +41 -59
- data/lib/mongo/protocol.rb +0 -1
- data/lib/mongo/query_cache.rb +7 -15
- data/lib/mongo/retryable/backpressure.rb +31 -0
- data/lib/mongo/retryable/base_worker.rb +39 -13
- data/lib/mongo/retryable/read_worker.rb +77 -21
- data/lib/mongo/retryable/retry_policy.rb +59 -0
- data/lib/mongo/retryable/write_worker.rb +155 -56
- data/lib/mongo/retryable.rb +70 -9
- data/lib/mongo/search_index/view.rb +1 -1
- data/lib/mongo/semaphore.rb +0 -1
- data/lib/mongo/server/app_metadata/environment.rb +3 -3
- data/lib/mongo/server/app_metadata.rb +4 -5
- data/lib/mongo/server/connection.rb +61 -61
- data/lib/mongo/server/connection_base.rb +43 -53
- data/lib/mongo/server/connection_common.rb +41 -64
- data/lib/mongo/server/connection_pool/generation_manager.rb +6 -11
- data/lib/mongo/server/connection_pool/populator.rb +1 -4
- data/lib/mongo/server/connection_pool.rb +195 -167
- data/lib/mongo/server/description/features.rb +23 -60
- data/lib/mongo/server/description/load_balancer.rb +0 -2
- data/lib/mongo/server/description.rb +117 -138
- data/lib/mongo/server/monitor/app_metadata.rb +3 -4
- data/lib/mongo/server/monitor/connection.rb +28 -35
- data/lib/mongo/server/monitor.rb +65 -60
- data/lib/mongo/server/pending_connection.rb +70 -71
- data/lib/mongo/server/push_monitor/connection.rb +0 -3
- data/lib/mongo/server/push_monitor.rb +21 -29
- data/lib/mongo/server/round_trip_time_calculator.rb +11 -17
- data/lib/mongo/server.rb +60 -93
- data/lib/mongo/server_selector/base.rb +133 -157
- data/lib/mongo/server_selector/nearest.rb +2 -5
- data/lib/mongo/server_selector/primary.rb +1 -5
- data/lib/mongo/server_selector/primary_preferred.rb +2 -6
- data/lib/mongo/server_selector/secondary.rb +2 -6
- data/lib/mongo/server_selector/secondary_preferred.rb +1 -5
- data/lib/mongo/server_selector.rb +3 -4
- data/lib/mongo/session/server_session.rb +6 -7
- data/lib/mongo/session/session_pool.rb +20 -34
- data/lib/mongo/session.rb +287 -188
- data/lib/mongo/socket/ocsp_cache.rb +8 -13
- data/lib/mongo/socket/ocsp_verifier.rb +69 -70
- data/lib/mongo/socket/ssl.rb +44 -43
- data/lib/mongo/socket/tcp.rb +5 -8
- data/lib/mongo/socket/unix.rb +0 -4
- data/lib/mongo/socket.rb +80 -102
- data/lib/mongo/srv/monitor.rb +6 -11
- data/lib/mongo/srv/resolver.rb +15 -24
- data/lib/mongo/srv/result.rb +18 -24
- data/lib/mongo/srv.rb +0 -1
- data/lib/mongo/timeout.rb +4 -11
- data/lib/mongo/topology_version.rb +8 -13
- data/lib/mongo/tracing/open_telemetry/command_tracer.rb +1 -1
- data/lib/mongo/tracing/open_telemetry/operation_tracer.rb +1 -1
- data/lib/mongo/tracing/open_telemetry/tracer.rb +1 -1
- data/lib/mongo/uri/options_mapper.rb +135 -126
- data/lib/mongo/uri/srv_protocol.rb +25 -38
- data/lib/mongo/uri.rb +95 -139
- data/lib/mongo/utils.rb +5 -12
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern/acknowledged.rb +0 -2
- data/lib/mongo/write_concern/base.rb +6 -6
- data/lib/mongo/write_concern/unacknowledged.rb +0 -2
- data/lib/mongo/write_concern.rb +14 -15
- data/lib/mongo.rb +1 -3
- data/mongo.gemspec +17 -17
- metadata +5 -5
- data/lib/mongo/error/server_api_not_supported.rb +0 -27
- data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +0 -32
- data/lib/mongo/operation/shared/validatable.rb +0 -87
data/lib/mongo/session.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# rubocop:todo all
|
|
3
2
|
|
|
4
3
|
# Copyright (C) 2017-2020 MongoDB Inc.
|
|
5
4
|
#
|
|
@@ -19,7 +18,6 @@ require 'mongo/session/session_pool'
|
|
|
19
18
|
require 'mongo/session/server_session'
|
|
20
19
|
|
|
21
20
|
module Mongo
|
|
22
|
-
|
|
23
21
|
# A logical session representing a set of sequential operations executed
|
|
24
22
|
# by an application that are related in some way.
|
|
25
23
|
#
|
|
@@ -36,10 +34,9 @@ module Mongo
|
|
|
36
34
|
# Initialize a Session.
|
|
37
35
|
#
|
|
38
36
|
# A session can be explicit or implicit. Lifetime of explicit sessions is
|
|
39
|
-
# managed by the application - applications
|
|
37
|
+
# managed by the application - applications explicitly create such sessions
|
|
40
38
|
# and explicitly end them. Implicit sessions are created automatically by
|
|
41
|
-
# the driver
|
|
42
|
-
# (3.6+), and their lifetime is managed by the driver.
|
|
39
|
+
# the driver, and their lifetime is managed by the driver.
|
|
43
40
|
#
|
|
44
41
|
# When an implicit session is created, it cannot have a server session
|
|
45
42
|
# associated with it. The server session will be checked out of the
|
|
@@ -89,20 +86,24 @@ module Mongo
|
|
|
89
86
|
unless server_session.nil?
|
|
90
87
|
raise ArgumentError, 'Implicit session cannot reference server session during construction'
|
|
91
88
|
end
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
raise ArgumentError, 'Explicit session must reference server session during construction'
|
|
95
|
-
end
|
|
89
|
+
elsif server_session.nil?
|
|
90
|
+
raise ArgumentError, 'Explicit session must reference server session during construction'
|
|
96
91
|
end
|
|
97
92
|
|
|
98
93
|
@server_session = server_session
|
|
99
94
|
options = options.dup
|
|
100
95
|
|
|
101
|
-
|
|
96
|
+
# Implicit sessions only need the cluster and client options (never run
|
|
97
|
+
# transactions), so avoid creating a Mongo::Client clone to prevent
|
|
98
|
+
# memory leaks: use the original client directly instead.
|
|
99
|
+
@client = options[:implicit] ? client : client.use(:admin)
|
|
100
|
+
@cluster = @client.cluster
|
|
102
101
|
@options = options.dup.freeze
|
|
103
102
|
@cluster_time = nil
|
|
104
103
|
@state = NO_TRANSACTION_STATE
|
|
105
104
|
@with_transaction_deadline = nil
|
|
105
|
+
@with_transaction_timeout_ms = nil
|
|
106
|
+
@inside_with_transaction = false
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
# @return [ Hash ] The options for this session.
|
|
@@ -115,9 +116,7 @@ module Mongo
|
|
|
115
116
|
# @since 2.5.1
|
|
116
117
|
attr_reader :client
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
@client.cluster
|
|
120
|
-
end
|
|
119
|
+
attr_reader :cluster
|
|
121
120
|
|
|
122
121
|
# @return [ true | false ] Whether the session is configured for snapshot
|
|
123
122
|
# reads.
|
|
@@ -154,7 +153,7 @@ module Mongo
|
|
|
154
153
|
#
|
|
155
154
|
# @since 2.6.0
|
|
156
155
|
def txn_options
|
|
157
|
-
@txn_options or raise ArgumentError,
|
|
156
|
+
@txn_options or raise ArgumentError, 'There is no active transaction'
|
|
158
157
|
end
|
|
159
158
|
|
|
160
159
|
# Is this session an implicit one (not user-created).
|
|
@@ -208,8 +207,8 @@ module Mongo
|
|
|
208
207
|
#
|
|
209
208
|
# @return [ true, false ] If writes will be retried.
|
|
210
209
|
#
|
|
211
|
-
# @note Retryable writes are only available
|
|
212
|
-
#
|
|
210
|
+
# @note Retryable writes are only available with sharded clusters, replica
|
|
211
|
+
# sets, or load-balanced topologies.
|
|
213
212
|
#
|
|
214
213
|
# @since 2.5.0
|
|
215
214
|
def retry_writes?
|
|
@@ -229,7 +228,7 @@ module Mongo
|
|
|
229
228
|
# @since 2.6.0
|
|
230
229
|
def txn_read_preference
|
|
231
230
|
rp = txn_options[:read] ||
|
|
232
|
-
|
|
231
|
+
@client.read_preference
|
|
233
232
|
Mongo::Lint.validate_underscore_read_preference(rp)
|
|
234
233
|
rp
|
|
235
234
|
end
|
|
@@ -255,9 +254,7 @@ module Mongo
|
|
|
255
254
|
#
|
|
256
255
|
# @since 2.5.0
|
|
257
256
|
def session_id
|
|
258
|
-
if ended?
|
|
259
|
-
raise Error::SessionEnded
|
|
260
|
-
end
|
|
257
|
+
raise Error::SessionEnded if ended?
|
|
261
258
|
|
|
262
259
|
# An explicit session will always have a session_id, because during
|
|
263
260
|
# construction a server session must be provided. An implicit session
|
|
@@ -266,9 +263,7 @@ module Mongo
|
|
|
266
263
|
# to experience this failure because an implicit session shouldn't be
|
|
267
264
|
# accessible to applications due to its lifetime being constrained to
|
|
268
265
|
# operation execution, which is done entirely by the driver.
|
|
269
|
-
unless materialized?
|
|
270
|
-
raise Error::SessionNotMaterialized
|
|
271
|
-
end
|
|
266
|
+
raise Error::SessionNotMaterialized unless materialized?
|
|
272
267
|
|
|
273
268
|
@server_session.session_id
|
|
274
269
|
end
|
|
@@ -296,20 +291,20 @@ module Mongo
|
|
|
296
291
|
#
|
|
297
292
|
# @since 2.5.0
|
|
298
293
|
MISMATCHED_CLUSTER_ERROR_MSG = 'The configuration of the client used to create this session does not match that ' +
|
|
299
|
-
|
|
300
|
-
|
|
294
|
+
'of the client owning this operation. Please only use this session for operations through its parent ' +
|
|
295
|
+
'client.'
|
|
301
296
|
|
|
302
297
|
# Error message describing that the session cannot be used because it has already been ended.
|
|
303
298
|
#
|
|
304
299
|
# @since 2.5.0
|
|
305
|
-
SESSION_ENDED_ERROR_MSG = 'This session has ended and cannot be used. Please create a new one.'
|
|
300
|
+
SESSION_ENDED_ERROR_MSG = 'This session has ended and cannot be used. Please create a new one.'
|
|
306
301
|
|
|
307
302
|
# Error message describing that sessions are not supported by the server version.
|
|
308
303
|
#
|
|
309
304
|
# @since 2.5.0
|
|
310
305
|
# @deprecated
|
|
311
|
-
SESSIONS_NOT_SUPPORTED = 'Sessions are not supported by the connected servers.'
|
|
312
|
-
#
|
|
306
|
+
SESSIONS_NOT_SUPPORTED = 'Sessions are not supported by the connected servers.'
|
|
307
|
+
# NOTE: SESSIONS_NOT_SUPPORTED is used by Mongoid 7.6 and earlier
|
|
313
308
|
|
|
314
309
|
# The state of a session in which the last operation was not related to
|
|
315
310
|
# any transaction or no operations have yet occurred.
|
|
@@ -384,13 +379,15 @@ module Mongo
|
|
|
384
379
|
rescue Mongo::Error, Error::AuthError
|
|
385
380
|
end
|
|
386
381
|
end
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
382
|
+
# Release any pinned connection (e.g. after a committed transaction
|
|
383
|
+
# in load-balanced mode).
|
|
384
|
+
unpin if pinned_connection_global_id
|
|
385
|
+
cluster.session_pool.checkin(@server_session) if @server_session
|
|
390
386
|
end
|
|
391
387
|
ensure
|
|
392
388
|
@server_session = nil
|
|
393
389
|
@ended = true
|
|
390
|
+
@client = nil
|
|
394
391
|
end
|
|
395
392
|
|
|
396
393
|
# Executes the provided block in a transaction, retrying as necessary.
|
|
@@ -448,38 +445,74 @@ module Mongo
|
|
|
448
445
|
#
|
|
449
446
|
# @since 2.7.0
|
|
450
447
|
def with_transaction(options = nil)
|
|
448
|
+
@inside_with_transaction = true
|
|
449
|
+
@with_transaction_timeout_ms = options&.dig(:timeout_ms) || @options[:default_timeout_ms] || @client.timeout_ms
|
|
451
450
|
@with_transaction_deadline = calculate_with_transaction_deadline(options)
|
|
452
451
|
deadline = if @with_transaction_deadline
|
|
453
452
|
# CSOT enabled, so we have a customer defined deadline.
|
|
454
453
|
@with_transaction_deadline
|
|
455
454
|
else
|
|
456
|
-
|
|
455
|
+
# CSOT not enabled, so we use the default deadline, 120 seconds.
|
|
457
456
|
Utils.monotonic_time + 120
|
|
458
457
|
end
|
|
459
458
|
transaction_in_progress = false
|
|
459
|
+
transaction_attempt = 0
|
|
460
|
+
last_error = nil
|
|
461
|
+
overload_error_count = 0
|
|
462
|
+
overload_encountered = false
|
|
463
|
+
|
|
460
464
|
loop do
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
465
|
+
if transaction_attempt > 0
|
|
466
|
+
if overload_encountered
|
|
467
|
+
delay = @client.retry_policy.backoff_delay(overload_error_count)
|
|
468
|
+
if backoff_would_exceed_deadline?(deadline, delay)
|
|
469
|
+
make_timeout_error_from(last_error, 'CSOT timeout expired waiting to retry withTransaction')
|
|
470
|
+
end
|
|
471
|
+
raise(last_error) unless @client.retry_policy.should_retry_overload?(overload_error_count, delay)
|
|
472
|
+
|
|
473
|
+
sleep(delay)
|
|
474
|
+
else
|
|
475
|
+
backoff = backoff_seconds_for_retry(transaction_attempt)
|
|
476
|
+
if backoff_would_exceed_deadline?(deadline, backoff)
|
|
477
|
+
make_timeout_error_from(last_error, 'CSOT timeout expired waiting to retry withTransaction')
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
sleep(backoff)
|
|
481
|
+
end
|
|
464
482
|
end
|
|
483
|
+
|
|
484
|
+
commit_options = {}
|
|
485
|
+
commit_options[:write_concern] = options[:write_concern] if options
|
|
465
486
|
start_transaction(options)
|
|
466
487
|
transaction_in_progress = true
|
|
488
|
+
transaction_attempt += 1
|
|
489
|
+
|
|
467
490
|
begin
|
|
468
491
|
rv = yield self
|
|
469
492
|
rescue Exception => e
|
|
470
493
|
if within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
|
|
471
494
|
log_warn("Aborting transaction due to #{e.class}: #{e}")
|
|
472
|
-
|
|
495
|
+
# CSOT: if the deadline is already expired, clear it so that
|
|
496
|
+
# abort_transaction uses a fresh timeout (not the expired deadline).
|
|
497
|
+
# If the deadline is not yet expired, keep it so abort uses remaining time.
|
|
498
|
+
@with_transaction_deadline = nil if @with_transaction_deadline && deadline_expired?(deadline)
|
|
473
499
|
abort_transaction
|
|
474
500
|
transaction_in_progress = false
|
|
475
501
|
end
|
|
476
502
|
|
|
477
503
|
if deadline_expired?(deadline)
|
|
478
504
|
transaction_in_progress = false
|
|
479
|
-
|
|
505
|
+
make_timeout_error_from(e, 'CSOT timeout expired during withTransaction callback')
|
|
480
506
|
end
|
|
481
507
|
|
|
482
508
|
if e.is_a?(Mongo::Error) && e.label?('TransientTransactionError')
|
|
509
|
+
last_error = e
|
|
510
|
+
if e.label?('SystemOverloadedError')
|
|
511
|
+
overload_encountered = true
|
|
512
|
+
overload_error_count += 1
|
|
513
|
+
elsif overload_encountered
|
|
514
|
+
overload_error_count += 1
|
|
515
|
+
end
|
|
483
516
|
next
|
|
484
517
|
end
|
|
485
518
|
|
|
@@ -490,32 +523,71 @@ module Mongo
|
|
|
490
523
|
return rv
|
|
491
524
|
end
|
|
492
525
|
|
|
526
|
+
# CSOT: if the timeout has expired before we can commit, abort the
|
|
527
|
+
# transaction instead and raise a client-side timeout error.
|
|
528
|
+
if @with_transaction_deadline && deadline_expired?(deadline)
|
|
529
|
+
transaction_in_progress = false
|
|
530
|
+
@with_transaction_deadline = nil
|
|
531
|
+
abort_transaction
|
|
532
|
+
raise Mongo::Error::TimeoutError, 'CSOT timeout expired before transaction could be committed'
|
|
533
|
+
end
|
|
534
|
+
|
|
493
535
|
begin
|
|
494
536
|
commit_transaction(commit_options)
|
|
495
537
|
transaction_in_progress = false
|
|
496
538
|
return rv
|
|
497
539
|
rescue Mongo::Error => e
|
|
498
540
|
if e.label?('UnknownTransactionCommitResult')
|
|
499
|
-
if
|
|
500
|
-
|
|
501
|
-
then
|
|
541
|
+
if deadline_expired?(deadline) ||
|
|
542
|
+
(e.is_a?(Error::OperationFailure::Family) && e.max_time_ms_expired?)
|
|
502
543
|
transaction_in_progress = false
|
|
503
|
-
|
|
544
|
+
|
|
545
|
+
raise unless @with_transaction_timeout_ms && deadline_expired?(deadline)
|
|
546
|
+
|
|
547
|
+
make_timeout_error_from(e, 'CSOT timeout expired during withTransaction commit')
|
|
504
548
|
end
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
549
|
+
|
|
550
|
+
if e.label?('SystemOverloadedError')
|
|
551
|
+
overload_encountered = true
|
|
552
|
+
overload_error_count += 1
|
|
553
|
+
elsif overload_encountered
|
|
554
|
+
overload_error_count += 1
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
if overload_encountered
|
|
558
|
+
delay = @client.retry_policy.backoff_delay(overload_error_count)
|
|
559
|
+
if backoff_would_exceed_deadline?(deadline, delay)
|
|
560
|
+
transaction_in_progress = false
|
|
561
|
+
make_timeout_error_from(e, 'CSOT timeout expired during withTransaction commit')
|
|
512
562
|
end
|
|
563
|
+
unless @client.retry_policy.should_retry_overload?(overload_error_count, delay)
|
|
564
|
+
transaction_in_progress = false
|
|
565
|
+
raise
|
|
566
|
+
end
|
|
567
|
+
sleep(delay)
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
wc_options = case v = commit_options[:write_concern]
|
|
571
|
+
when WriteConcern::Base
|
|
572
|
+
v.options
|
|
573
|
+
when nil
|
|
574
|
+
{}
|
|
575
|
+
else
|
|
576
|
+
v
|
|
577
|
+
end
|
|
513
578
|
commit_options[:write_concern] = wc_options.merge(w: :majority)
|
|
514
579
|
retry
|
|
515
580
|
elsif e.label?('TransientTransactionError')
|
|
516
581
|
if Utils.monotonic_time >= deadline
|
|
517
582
|
transaction_in_progress = false
|
|
518
|
-
|
|
583
|
+
make_timeout_error_from(e, 'CSOT timeout expired during withTransaction commit')
|
|
584
|
+
end
|
|
585
|
+
last_error = e
|
|
586
|
+
if e.label?('SystemOverloadedError')
|
|
587
|
+
overload_encountered = true
|
|
588
|
+
overload_error_count += 1
|
|
589
|
+
elsif overload_encountered
|
|
590
|
+
overload_error_count += 1
|
|
519
591
|
end
|
|
520
592
|
@state = NO_TRANSACTION_STATE
|
|
521
593
|
next
|
|
@@ -542,6 +614,8 @@ module Mongo
|
|
|
542
614
|
end
|
|
543
615
|
end
|
|
544
616
|
@with_transaction_deadline = nil
|
|
617
|
+
@with_transaction_timeout_ms = nil
|
|
618
|
+
@inside_with_transaction = false
|
|
545
619
|
end
|
|
546
620
|
|
|
547
621
|
# Places subsequent operations in this session into a new transaction.
|
|
@@ -556,7 +630,7 @@ module Mongo
|
|
|
556
630
|
#
|
|
557
631
|
# @option options [ Integer ] :max_commit_time_ms The maximum amount of
|
|
558
632
|
# time to allow a single commitTransaction command to run, in milliseconds.
|
|
559
|
-
# This
|
|
633
|
+
# This option is deprecated, use :timeout_ms instead.
|
|
560
634
|
# @option options [ Hash ] :read_concern The read concern options hash,
|
|
561
635
|
# with the following optional keys:
|
|
562
636
|
# - *:level* -- the read preference level as a symbol; valid values
|
|
@@ -582,28 +656,25 @@ module Mongo
|
|
|
582
656
|
if options
|
|
583
657
|
Lint.validate_read_concern_option(options[:read_concern])
|
|
584
658
|
|
|
585
|
-
|
|
586
|
-
#
|
|
587
|
-
#
|
|
588
|
-
#
|
|
589
|
-
mode
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
end
|
|
595
|
-
=end
|
|
659
|
+
# # It would be handy to detect invalid read preferences here, but
|
|
660
|
+
# # some of the spec tests require later detection of invalid read prefs.
|
|
661
|
+
# # Maybe we can do this when lint mode is on.
|
|
662
|
+
# mode = options[:read] && options[:read][:mode].to_s
|
|
663
|
+
# if mode && mode != 'primary'
|
|
664
|
+
# raise Mongo::Error::InvalidTransactionOperation.new(
|
|
665
|
+
# "read preference in a transaction must be primary (requested: #{mode})"
|
|
666
|
+
# )
|
|
667
|
+
# end
|
|
596
668
|
end
|
|
597
669
|
|
|
598
|
-
if snapshot?
|
|
599
|
-
raise Mongo::Error::SnapshotSessionTransactionProhibited
|
|
600
|
-
end
|
|
670
|
+
raise Mongo::Error::SnapshotSessionTransactionProhibited if snapshot?
|
|
601
671
|
|
|
602
672
|
check_if_ended!
|
|
603
673
|
|
|
604
674
|
if within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
|
|
605
675
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
606
|
-
Mongo::Error::InvalidTransactionOperation::TRANSACTION_ALREADY_IN_PROGRESS
|
|
676
|
+
Mongo::Error::InvalidTransactionOperation::TRANSACTION_ALREADY_IN_PROGRESS
|
|
677
|
+
)
|
|
607
678
|
end
|
|
608
679
|
|
|
609
680
|
unpin
|
|
@@ -613,7 +684,8 @@ module Mongo
|
|
|
613
684
|
|
|
614
685
|
if txn_write_concern && !WriteConcern.get(txn_write_concern).acknowledged?
|
|
615
686
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
616
|
-
Mongo::Error::InvalidTransactionOperation::UNACKNOWLEDGED_WRITE_CONCERN
|
|
687
|
+
Mongo::Error::InvalidTransactionOperation::UNACKNOWLEDGED_WRITE_CONCERN
|
|
688
|
+
)
|
|
617
689
|
end
|
|
618
690
|
|
|
619
691
|
@state = STARTING_TRANSACTION_STATE
|
|
@@ -642,7 +714,7 @@ module Mongo
|
|
|
642
714
|
# @raise [ Error::InvalidTransactionOperation ] If there is no active transaction.
|
|
643
715
|
#
|
|
644
716
|
# @since 2.6.0
|
|
645
|
-
def commit_transaction(options=nil)
|
|
717
|
+
def commit_transaction(options = nil)
|
|
646
718
|
QueryCache.clear
|
|
647
719
|
check_if_ended!
|
|
648
720
|
check_if_no_transaction!
|
|
@@ -650,7 +722,9 @@ module Mongo
|
|
|
650
722
|
if within_states?(TRANSACTION_ABORTED_STATE)
|
|
651
723
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
652
724
|
Mongo::Error::InvalidTransactionOperation.cannot_call_after_msg(
|
|
653
|
-
:abortTransaction, :commitTransaction
|
|
725
|
+
:abortTransaction, :commitTransaction
|
|
726
|
+
)
|
|
727
|
+
)
|
|
654
728
|
end
|
|
655
729
|
|
|
656
730
|
options ||= {}
|
|
@@ -670,9 +744,7 @@ module Mongo
|
|
|
670
744
|
@committing_transaction = true
|
|
671
745
|
|
|
672
746
|
write_concern = options[:write_concern] || txn_options[:write_concern]
|
|
673
|
-
if write_concern && !write_concern.is_a?(WriteConcern::Base)
|
|
674
|
-
write_concern = WriteConcern.get(write_concern)
|
|
675
|
-
end
|
|
747
|
+
write_concern = WriteConcern.get(write_concern) if write_concern && !write_concern.is_a?(WriteConcern::Base)
|
|
676
748
|
|
|
677
749
|
context = Operation::Context.new(
|
|
678
750
|
client: @client,
|
|
@@ -680,15 +752,14 @@ module Mongo
|
|
|
680
752
|
operation_timeouts: operation_timeouts(options)
|
|
681
753
|
)
|
|
682
754
|
write_with_retry(write_concern, ending_transaction: true,
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
if context.retry?
|
|
755
|
+
context: context) do |connection, txn_num, context|
|
|
756
|
+
if context.retry? && !context.overload_only_retry?
|
|
686
757
|
if write_concern
|
|
687
758
|
wco = write_concern.options.merge(w: :majority)
|
|
688
|
-
wco[:wtimeout] ||=
|
|
759
|
+
wco[:wtimeout] ||= 10_000
|
|
689
760
|
write_concern = WriteConcern.get(wco)
|
|
690
761
|
else
|
|
691
|
-
write_concern = WriteConcern.get(w: :majority, wtimeout:
|
|
762
|
+
write_concern = WriteConcern.get(w: :majority, wtimeout: 10_000)
|
|
692
763
|
end
|
|
693
764
|
end
|
|
694
765
|
spec = {
|
|
@@ -738,12 +809,15 @@ module Mongo
|
|
|
738
809
|
if within_states?(TRANSACTION_COMMITTED_STATE)
|
|
739
810
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
740
811
|
Mongo::Error::InvalidTransactionOperation.cannot_call_after_msg(
|
|
741
|
-
:commitTransaction, :abortTransaction
|
|
812
|
+
:commitTransaction, :abortTransaction
|
|
813
|
+
)
|
|
814
|
+
)
|
|
742
815
|
end
|
|
743
816
|
|
|
744
817
|
if within_states?(TRANSACTION_ABORTED_STATE)
|
|
745
818
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
746
|
-
Mongo::Error::InvalidTransactionOperation.cannot_call_twice_msg(:abortTransaction)
|
|
819
|
+
Mongo::Error::InvalidTransactionOperation.cannot_call_twice_msg(:abortTransaction)
|
|
820
|
+
)
|
|
747
821
|
end
|
|
748
822
|
|
|
749
823
|
options ||= {}
|
|
@@ -757,21 +831,18 @@ module Mongo
|
|
|
757
831
|
operation_timeouts: operation_timeouts(options)
|
|
758
832
|
)
|
|
759
833
|
write_with_retry(txn_options[:write_concern],
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
)
|
|
769
|
-
tracer.trace_operation(operation, context, op_name: 'abortTransaction') do
|
|
770
|
-
operation.execute_with_connection(connection, context: context)
|
|
771
|
-
end
|
|
772
|
-
ensure
|
|
773
|
-
unpin
|
|
834
|
+
ending_transaction: true, context: context) do |connection, txn_num, context|
|
|
835
|
+
operation = Operation::Command.new(
|
|
836
|
+
selector: { abortTransaction: 1 },
|
|
837
|
+
db_name: 'admin',
|
|
838
|
+
session: self,
|
|
839
|
+
txn_num: txn_num
|
|
840
|
+
)
|
|
841
|
+
tracer.trace_operation(operation, context, op_name: 'abortTransaction') do
|
|
842
|
+
operation.execute_with_connection(connection, context: context)
|
|
774
843
|
end
|
|
844
|
+
ensure
|
|
845
|
+
unpin
|
|
775
846
|
end
|
|
776
847
|
end
|
|
777
848
|
|
|
@@ -835,14 +906,12 @@ module Mongo
|
|
|
835
906
|
#
|
|
836
907
|
# @api private
|
|
837
908
|
def pin_to_server(server)
|
|
838
|
-
if server.nil?
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
unless server.mongos?
|
|
843
|
-
raise Error::LintError, "Attempted to pin the session to server #{server.summary} which is not a mongos"
|
|
844
|
-
end
|
|
909
|
+
raise ArgumentError, 'Cannot pin to a nil server' if server.nil?
|
|
910
|
+
|
|
911
|
+
if Lint.enabled? && !server.mongos?
|
|
912
|
+
raise Error::LintError, "Attempted to pin the session to server #{server.summary} which is not a mongos"
|
|
845
913
|
end
|
|
914
|
+
|
|
846
915
|
@pinned_server = server
|
|
847
916
|
end
|
|
848
917
|
|
|
@@ -850,13 +919,14 @@ module Mongo
|
|
|
850
919
|
#
|
|
851
920
|
# @param [ Integer ] connection_global_id The global id of connection to pin
|
|
852
921
|
# this session to.
|
|
922
|
+
# @param [ Connection | nil ] connection The connection object to pin to.
|
|
853
923
|
#
|
|
854
924
|
# @api private
|
|
855
|
-
def pin_to_connection(connection_global_id)
|
|
856
|
-
if connection_global_id.nil?
|
|
857
|
-
|
|
858
|
-
end
|
|
925
|
+
def pin_to_connection(connection_global_id, connection: nil)
|
|
926
|
+
raise ArgumentError, 'Cannot pin to a nil connection id' if connection_global_id.nil?
|
|
927
|
+
|
|
859
928
|
@pinned_connection_global_id = connection_global_id
|
|
929
|
+
@pinned_connection = connection
|
|
860
930
|
end
|
|
861
931
|
|
|
862
932
|
# Unpins this session from the pinned server or connection,
|
|
@@ -868,7 +938,16 @@ module Mongo
|
|
|
868
938
|
def unpin(connection = nil)
|
|
869
939
|
@pinned_server = nil
|
|
870
940
|
@pinned_connection_global_id = nil
|
|
871
|
-
connection
|
|
941
|
+
conn = connection || @pinned_connection
|
|
942
|
+
if conn
|
|
943
|
+
conn.unpin(:transaction)
|
|
944
|
+
# Only check the connection back into the pool if nothing else
|
|
945
|
+
# still holds a pin on it (e.g. an open cursor).
|
|
946
|
+
unless conn.pinned?
|
|
947
|
+
conn.connection_pool.check_in(conn)
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
@pinned_connection = nil
|
|
872
951
|
end
|
|
873
952
|
|
|
874
953
|
# Unpins this session from the pinned server or connection, if the session was pinned
|
|
@@ -884,14 +963,12 @@ module Mongo
|
|
|
884
963
|
# @api private
|
|
885
964
|
def unpin_maybe(error, connection = nil)
|
|
886
965
|
if !within_states?(Session::NO_TRANSACTION_STATE) &&
|
|
887
|
-
|
|
888
|
-
then
|
|
966
|
+
error.label?('TransientTransactionError')
|
|
889
967
|
unpin(connection)
|
|
890
968
|
end
|
|
891
969
|
|
|
892
970
|
if committing_transaction? &&
|
|
893
|
-
|
|
894
|
-
then
|
|
971
|
+
error.label?('UnknownTransactionCommitResult')
|
|
895
972
|
unpin(connection)
|
|
896
973
|
end
|
|
897
974
|
end
|
|
@@ -922,9 +999,7 @@ module Mongo
|
|
|
922
999
|
# @api private
|
|
923
1000
|
def add_start_transaction!(command)
|
|
924
1001
|
command.tap do |c|
|
|
925
|
-
if starting_transaction?
|
|
926
|
-
c[:startTransaction] = true
|
|
927
|
-
end
|
|
1002
|
+
c[:startTransaction] = true if starting_transaction?
|
|
928
1003
|
end
|
|
929
1004
|
end
|
|
930
1005
|
|
|
@@ -952,7 +1027,7 @@ module Mongo
|
|
|
952
1027
|
#
|
|
953
1028
|
# @since 2.6.0
|
|
954
1029
|
# @api private
|
|
955
|
-
def add_txn_opts!(command,
|
|
1030
|
+
def add_txn_opts!(command, _read, context)
|
|
956
1031
|
command.tap do |c|
|
|
957
1032
|
# The read concern should be added to any command that starts a transaction.
|
|
958
1033
|
if starting_transaction?
|
|
@@ -975,27 +1050,23 @@ module Mongo
|
|
|
975
1050
|
if rc.nil? || rc.empty?
|
|
976
1051
|
c.delete(:readConcern)
|
|
977
1052
|
else
|
|
978
|
-
c[:readConcern
|
|
1053
|
+
c[:readConcern] = Options::Mapper.transform_values_to_strings(rc)
|
|
979
1054
|
end
|
|
980
1055
|
end
|
|
981
1056
|
|
|
982
1057
|
# We need to send the read concern level as a string rather than a symbol.
|
|
983
|
-
if c[:readConcern]
|
|
984
|
-
c[:readConcern] = Options::Mapper.transform_values_to_strings(c[:readConcern])
|
|
985
|
-
end
|
|
1058
|
+
c[:readConcern] = Options::Mapper.transform_values_to_strings(c[:readConcern]) if c[:readConcern]
|
|
986
1059
|
|
|
987
|
-
if c[:commitTransaction]
|
|
988
|
-
|
|
989
|
-
c[:maxTimeMS] = max_time_ms
|
|
990
|
-
end
|
|
1060
|
+
if c[:commitTransaction] && (max_time_ms = txn_options[:max_commit_time_ms])
|
|
1061
|
+
c[:maxTimeMS] = max_time_ms
|
|
991
1062
|
end
|
|
992
1063
|
|
|
993
1064
|
# The write concern should be added to any abortTransaction or commitTransaction command.
|
|
994
|
-
if
|
|
1065
|
+
if c[:abortTransaction] || c[:commitTransaction]
|
|
995
1066
|
if @already_committed
|
|
996
1067
|
wc = BSON::Document.new(c[:writeConcern] || txn_write_concern || {})
|
|
997
1068
|
wc.merge!(w: :majority)
|
|
998
|
-
wc[:wtimeout] ||=
|
|
1069
|
+
wc[:wtimeout] ||= 10_000
|
|
999
1070
|
c[:writeConcern] = wc
|
|
1000
1071
|
elsif txn_write_concern
|
|
1001
1072
|
c[:writeConcern] ||= txn_write_concern
|
|
@@ -1008,12 +1079,10 @@ module Mongo
|
|
|
1008
1079
|
end
|
|
1009
1080
|
|
|
1010
1081
|
# Ignore wtimeout if csot
|
|
1011
|
-
if context&.csot?
|
|
1012
|
-
c[:writeConcern]&.delete(:wtimeout)
|
|
1013
|
-
end
|
|
1082
|
+
c[:writeConcern]&.delete(:wtimeout) if context&.csot?
|
|
1014
1083
|
|
|
1015
1084
|
# We must not send an empty (server default) write concern.
|
|
1016
|
-
c.delete(:writeConcern) if c[:writeConcern]
|
|
1085
|
+
c.delete(:writeConcern) if c[:writeConcern] && c[:writeConcern].empty?
|
|
1017
1086
|
end
|
|
1018
1087
|
end
|
|
1019
1088
|
|
|
@@ -1035,7 +1104,7 @@ module Mongo
|
|
|
1035
1104
|
end
|
|
1036
1105
|
end
|
|
1037
1106
|
|
|
1038
|
-
# Ensure that the read preference of a command primary.
|
|
1107
|
+
# Ensure that the read preference of a command is primary.
|
|
1039
1108
|
#
|
|
1040
1109
|
# @example
|
|
1041
1110
|
# session.validate_read_preference!(command)
|
|
@@ -1051,11 +1120,21 @@ module Mongo
|
|
|
1051
1120
|
|
|
1052
1121
|
mode = command['$readPreference']['mode'] || command['$readPreference'][:mode]
|
|
1053
1122
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
)
|
|
1058
|
-
|
|
1123
|
+
return unless mode && mode != 'primary'
|
|
1124
|
+
|
|
1125
|
+
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
1126
|
+
"read preference in a transaction must be primary (requested: #{mode})"
|
|
1127
|
+
)
|
|
1128
|
+
end
|
|
1129
|
+
|
|
1130
|
+
# Reverts the session state to STARTING_TRANSACTION_STATE.
|
|
1131
|
+
# Called before retrying the first command in a transaction so that
|
|
1132
|
+
# startTransaction: true is preserved on the retry.
|
|
1133
|
+
# @api private
|
|
1134
|
+
def revert_to_starting_transaction!
|
|
1135
|
+
return unless within_states?(TRANSACTION_IN_PROGRESS_STATE)
|
|
1136
|
+
|
|
1137
|
+
@state = STARTING_TRANSACTION_STATE
|
|
1059
1138
|
end
|
|
1060
1139
|
|
|
1061
1140
|
# Update the state of the session due to a (non-commit and non-abort) operation being run.
|
|
@@ -1085,8 +1164,8 @@ module Mongo
|
|
|
1085
1164
|
# @since 2.5.0
|
|
1086
1165
|
# @api private
|
|
1087
1166
|
def validate!(client)
|
|
1088
|
-
check_matching_cluster!(client)
|
|
1089
1167
|
check_if_ended!
|
|
1168
|
+
check_matching_cluster!(client)
|
|
1090
1169
|
self
|
|
1091
1170
|
end
|
|
1092
1171
|
|
|
@@ -1110,10 +1189,8 @@ module Mongo
|
|
|
1110
1189
|
end
|
|
1111
1190
|
@server_session.set_last_use!
|
|
1112
1191
|
|
|
1113
|
-
if doc = result.reply && result.reply.documents.first
|
|
1114
|
-
|
|
1115
|
-
self.recovery_token = doc[:recoveryToken]
|
|
1116
|
-
end
|
|
1192
|
+
if (doc = result.reply && result.reply.documents.first) && doc[:recoveryToken]
|
|
1193
|
+
self.recovery_token = doc[:recoveryToken]
|
|
1117
1194
|
end
|
|
1118
1195
|
|
|
1119
1196
|
result
|
|
@@ -1130,11 +1207,11 @@ module Mongo
|
|
|
1130
1207
|
#
|
|
1131
1208
|
# @since 2.5.0
|
|
1132
1209
|
def advance_operation_time(new_operation_time)
|
|
1133
|
-
if @operation_time
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1210
|
+
@operation_time = if @operation_time
|
|
1211
|
+
[ @operation_time, new_operation_time ].max
|
|
1212
|
+
else
|
|
1213
|
+
new_operation_time
|
|
1214
|
+
end
|
|
1138
1215
|
end
|
|
1139
1216
|
|
|
1140
1217
|
# If not already set, populate a session objects's server_session by
|
|
@@ -1144,9 +1221,7 @@ module Mongo
|
|
|
1144
1221
|
#
|
|
1145
1222
|
# @api private
|
|
1146
1223
|
def materialize_if_needed
|
|
1147
|
-
if ended?
|
|
1148
|
-
raise Error::SessionEnded
|
|
1149
|
-
end
|
|
1224
|
+
raise Error::SessionEnded if ended?
|
|
1150
1225
|
|
|
1151
1226
|
return unless implicit? && !@server_session
|
|
1152
1227
|
|
|
@@ -1157,9 +1232,7 @@ module Mongo
|
|
|
1157
1232
|
|
|
1158
1233
|
# @api private
|
|
1159
1234
|
def materialized?
|
|
1160
|
-
if ended?
|
|
1161
|
-
raise Error::SessionEnded
|
|
1162
|
-
end
|
|
1235
|
+
raise Error::SessionEnded if ended?
|
|
1163
1236
|
|
|
1164
1237
|
!@server_session.nil?
|
|
1165
1238
|
end
|
|
@@ -1174,9 +1247,7 @@ module Mongo
|
|
|
1174
1247
|
# @since 2.5.0
|
|
1175
1248
|
# @api private
|
|
1176
1249
|
def next_txn_num
|
|
1177
|
-
if ended?
|
|
1178
|
-
raise Error::SessionEnded
|
|
1179
|
-
end
|
|
1250
|
+
raise Error::SessionEnded if ended?
|
|
1180
1251
|
|
|
1181
1252
|
@server_session.next_txn_num
|
|
1182
1253
|
end
|
|
@@ -1190,9 +1261,7 @@ module Mongo
|
|
|
1190
1261
|
#
|
|
1191
1262
|
# @since 2.6.0
|
|
1192
1263
|
def txn_num
|
|
1193
|
-
if ended?
|
|
1194
|
-
raise Error::SessionEnded
|
|
1195
|
-
end
|
|
1264
|
+
raise Error::SessionEnded if ended?
|
|
1196
1265
|
|
|
1197
1266
|
@server_session.txn_num
|
|
1198
1267
|
end
|
|
@@ -1204,6 +1273,12 @@ module Mongo
|
|
|
1204
1273
|
# @api private
|
|
1205
1274
|
attr_reader :with_transaction_deadline
|
|
1206
1275
|
|
|
1276
|
+
# @return [ Boolean ] Whether we are currently inside a with_transaction block.
|
|
1277
|
+
# @api private
|
|
1278
|
+
def inside_with_transaction?
|
|
1279
|
+
@inside_with_transaction
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1207
1282
|
private
|
|
1208
1283
|
|
|
1209
1284
|
# Get the read concern the session will use when starting a transaction.
|
|
@@ -1229,7 +1304,8 @@ module Mongo
|
|
|
1229
1304
|
return unless within_states?(NO_TRANSACTION_STATE)
|
|
1230
1305
|
|
|
1231
1306
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
1232
|
-
Mongo::Error::InvalidTransactionOperation::NO_TRANSACTION_STARTED
|
|
1307
|
+
Mongo::Error::InvalidTransactionOperation::NO_TRANSACTION_STARTED
|
|
1308
|
+
)
|
|
1233
1309
|
end
|
|
1234
1310
|
|
|
1235
1311
|
def txn_write_concern
|
|
@@ -1240,25 +1316,23 @@ module Mongo
|
|
|
1240
1316
|
# Returns causal consistency document if the last operation time is
|
|
1241
1317
|
# known and causal consistency is enabled, otherwise returns nil.
|
|
1242
1318
|
def causal_consistency_doc
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
nil
|
|
1247
|
-
end
|
|
1319
|
+
return unless operation_time && causal_consistency?
|
|
1320
|
+
|
|
1321
|
+
{ afterClusterTime: operation_time }
|
|
1248
1322
|
end
|
|
1249
1323
|
|
|
1250
1324
|
def causal_consistency?
|
|
1251
|
-
@causal_consistency ||=
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1325
|
+
@causal_consistency ||= if @options.key?(:causal_consistency)
|
|
1326
|
+
!!@options[:causal_consistency]
|
|
1327
|
+
else
|
|
1328
|
+
true
|
|
1329
|
+
end
|
|
1256
1330
|
end
|
|
1257
1331
|
|
|
1258
1332
|
def set_operation_time(result)
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1333
|
+
return unless result && result.operation_time
|
|
1334
|
+
|
|
1335
|
+
@operation_time = result.operation_time
|
|
1262
1336
|
end
|
|
1263
1337
|
|
|
1264
1338
|
def check_if_ended!
|
|
@@ -1266,40 +1340,34 @@ module Mongo
|
|
|
1266
1340
|
end
|
|
1267
1341
|
|
|
1268
1342
|
def check_matching_cluster!(client)
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1343
|
+
return unless cluster != client.cluster
|
|
1344
|
+
|
|
1345
|
+
raise Mongo::Error::InvalidSession.new(MISMATCHED_CLUSTER_ERROR_MSG)
|
|
1272
1346
|
end
|
|
1273
1347
|
|
|
1274
1348
|
def check_transactions_supported!
|
|
1275
|
-
raise Mongo::Error::TransactionsNotSupported,
|
|
1276
|
-
|
|
1277
|
-
cluster.next_primary.with_connection do |conn|
|
|
1278
|
-
if cluster.replica_set? && !conn.features.transactions_enabled?
|
|
1279
|
-
raise Mongo::Error::TransactionsNotSupported, "server version is < 4.0"
|
|
1280
|
-
end
|
|
1281
|
-
if cluster.sharded? && !conn.features.sharded_transactions_enabled?
|
|
1282
|
-
raise Mongo::Error::TransactionsNotSupported, "sharded transactions require server version >= 4.2"
|
|
1283
|
-
end
|
|
1284
|
-
end
|
|
1349
|
+
raise Mongo::Error::TransactionsNotSupported, 'standalone topology' if cluster.single?
|
|
1285
1350
|
end
|
|
1286
1351
|
|
|
1287
1352
|
def operation_timeouts(opts)
|
|
1288
1353
|
{
|
|
1289
|
-
inherited_timeout_ms: @client.timeout_ms
|
|
1354
|
+
inherited_timeout_ms: @with_transaction_timeout_ms || @client.timeout_ms
|
|
1290
1355
|
}.tap do |result|
|
|
1291
|
-
if @
|
|
1292
|
-
if
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
result[:operation_timeout_ms] = default_timeout_ms
|
|
1356
|
+
if @inside_with_transaction
|
|
1357
|
+
if opts[:timeout_ms]
|
|
1358
|
+
raise Mongo::Error::InvalidTransactionOperation,
|
|
1359
|
+
'timeoutMS cannot be overridden inside a withTransaction callback'
|
|
1296
1360
|
end
|
|
1361
|
+
elsif timeout_ms = opts[:timeout_ms]
|
|
1362
|
+
result[:operation_timeout_ms] = timeout_ms
|
|
1363
|
+
elsif default_timeout_ms = options[:default_timeout_ms]
|
|
1364
|
+
result[:operation_timeout_ms] = default_timeout_ms
|
|
1297
1365
|
end
|
|
1298
1366
|
end
|
|
1299
1367
|
end
|
|
1300
1368
|
|
|
1301
1369
|
def calculate_with_transaction_deadline(opts)
|
|
1302
|
-
calc =
|
|
1370
|
+
calc = lambda { |timeout|
|
|
1303
1371
|
if timeout == 0
|
|
1304
1372
|
0
|
|
1305
1373
|
else
|
|
@@ -1322,5 +1390,36 @@ module Mongo
|
|
|
1322
1390
|
Utils.monotonic_time >= deadline
|
|
1323
1391
|
end
|
|
1324
1392
|
end
|
|
1393
|
+
|
|
1394
|
+
# Exponential backoff settings for with_transaction retries.
|
|
1395
|
+
BACKOFF_INITIAL = 0.005
|
|
1396
|
+
BACKOFF_MAX = 0.5
|
|
1397
|
+
private_constant :BACKOFF_INITIAL, :BACKOFF_MAX
|
|
1398
|
+
|
|
1399
|
+
def backoff_seconds_for_retry(transaction_attempt)
|
|
1400
|
+
exponential = BACKOFF_INITIAL * (1.5**(transaction_attempt - 1))
|
|
1401
|
+
Random.rand * [ exponential, BACKOFF_MAX ].min
|
|
1402
|
+
end
|
|
1403
|
+
|
|
1404
|
+
def backoff_would_exceed_deadline?(deadline, backoff_seconds)
|
|
1405
|
+
return false if deadline.zero?
|
|
1406
|
+
|
|
1407
|
+
Utils.monotonic_time + backoff_seconds >= deadline
|
|
1408
|
+
end
|
|
1409
|
+
|
|
1410
|
+
# Implements makeTimeoutError(lastError) from the transactions-convenient-api spec.
|
|
1411
|
+
# In CSOT mode raises TimeoutError with last_error's message and labels copied.
|
|
1412
|
+
# In non-CSOT mode re-raises last_error directly.
|
|
1413
|
+
def make_timeout_error_from(last_error, timeout_message)
|
|
1414
|
+
if @with_transaction_timeout_ms
|
|
1415
|
+
timeout_error = Mongo::Error::TimeoutError.new("#{timeout_message}: #{last_error}")
|
|
1416
|
+
if last_error.respond_to?(:labels)
|
|
1417
|
+
last_error.labels.each { |label| timeout_error.add_label(label) }
|
|
1418
|
+
end
|
|
1419
|
+
raise timeout_error
|
|
1420
|
+
end
|
|
1421
|
+
|
|
1422
|
+
raise last_error
|
|
1423
|
+
end
|
|
1325
1424
|
end
|
|
1326
1425
|
end
|