mongo 2.22.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 +267 -276
- 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 +152 -184
- data/lib/mongo/cluster_time.rb +14 -31
- data/lib/mongo/collection/helpers.rb +5 -8
- data/lib/mongo/collection/view/aggregation/behavior.rb +1 -1
- data/lib/mongo/collection/view/aggregation.rb +10 -12
- 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 +44 -35
- data/lib/mongo/collection/view/map_reduce.rb +20 -25
- data/lib/mongo/collection/view/readable.rb +96 -94
- data/lib/mongo/collection/view/writable.rb +104 -114
- data/lib/mongo/collection/view.rb +11 -8
- data/lib/mongo/collection.rb +103 -106
- 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 +6 -4
- data/lib/mongo/crypt/auto_decryption_context.rb +9 -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 +150 -156
- data/lib/mongo/crypt/context.rb +20 -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 +9 -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 +23 -39
- data/lib/mongo/database.rb +68 -65
- data/lib/mongo/dbref.rb +0 -1
- data/lib/mongo/deprecations.rb +98 -0
- 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 +68 -58
- 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 +4 -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 +7 -6
- 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 +29 -31
- 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 +37 -59
- 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 +30 -10
- data/lib/mongo/semaphore.rb +0 -1
- data/lib/mongo/server/app_metadata/environment.rb +3 -3
- data/lib/mongo/server/app_metadata/platform.rb +17 -4
- data/lib/mongo/server/app_metadata.rb +4 -5
- data/lib/mongo/server/connection.rb +79 -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 +51 -59
- 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 +62 -94
- 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 +334 -199
- 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 +10 -11
- data/lib/mongo/srv/resolver.rb +15 -24
- data/lib/mongo/srv/result.rb +25 -21
- 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 +320 -0
- data/lib/mongo/tracing/open_telemetry/operation_tracer.rb +227 -0
- data/lib/mongo/tracing/open_telemetry/tracer.rb +236 -0
- data/lib/mongo/{error/server_api_not_supported.rb → tracing/open_telemetry.rb} +10 -10
- data/lib/mongo/tracing.rb +42 -0
- data/lib/mongo/uri/options_mapper.rb +135 -126
- data/lib/mongo/uri/srv_protocol.rb +34 -42
- 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 +4 -3
- data/mongo.gemspec +17 -17
- metadata +11 -5
- 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.
|
|
@@ -130,6 +129,8 @@ module Mongo
|
|
|
130
129
|
# @since 2.5.0
|
|
131
130
|
attr_reader :operation_time
|
|
132
131
|
|
|
132
|
+
def_delegators :client, :tracer
|
|
133
|
+
|
|
133
134
|
# Sets the dirty state to the given value for the underlying server
|
|
134
135
|
# session. If there is no server session, this does nothing.
|
|
135
136
|
#
|
|
@@ -152,7 +153,7 @@ module Mongo
|
|
|
152
153
|
#
|
|
153
154
|
# @since 2.6.0
|
|
154
155
|
def txn_options
|
|
155
|
-
@txn_options or raise ArgumentError,
|
|
156
|
+
@txn_options or raise ArgumentError, 'There is no active transaction'
|
|
156
157
|
end
|
|
157
158
|
|
|
158
159
|
# Is this session an implicit one (not user-created).
|
|
@@ -206,8 +207,8 @@ module Mongo
|
|
|
206
207
|
#
|
|
207
208
|
# @return [ true, false ] If writes will be retried.
|
|
208
209
|
#
|
|
209
|
-
# @note Retryable writes are only available
|
|
210
|
-
#
|
|
210
|
+
# @note Retryable writes are only available with sharded clusters, replica
|
|
211
|
+
# sets, or load-balanced topologies.
|
|
211
212
|
#
|
|
212
213
|
# @since 2.5.0
|
|
213
214
|
def retry_writes?
|
|
@@ -227,7 +228,7 @@ module Mongo
|
|
|
227
228
|
# @since 2.6.0
|
|
228
229
|
def txn_read_preference
|
|
229
230
|
rp = txn_options[:read] ||
|
|
230
|
-
|
|
231
|
+
@client.read_preference
|
|
231
232
|
Mongo::Lint.validate_underscore_read_preference(rp)
|
|
232
233
|
rp
|
|
233
234
|
end
|
|
@@ -253,9 +254,7 @@ module Mongo
|
|
|
253
254
|
#
|
|
254
255
|
# @since 2.5.0
|
|
255
256
|
def session_id
|
|
256
|
-
if ended?
|
|
257
|
-
raise Error::SessionEnded
|
|
258
|
-
end
|
|
257
|
+
raise Error::SessionEnded if ended?
|
|
259
258
|
|
|
260
259
|
# An explicit session will always have a session_id, because during
|
|
261
260
|
# construction a server session must be provided. An implicit session
|
|
@@ -264,9 +263,7 @@ module Mongo
|
|
|
264
263
|
# to experience this failure because an implicit session shouldn't be
|
|
265
264
|
# accessible to applications due to its lifetime being constrained to
|
|
266
265
|
# operation execution, which is done entirely by the driver.
|
|
267
|
-
unless materialized?
|
|
268
|
-
raise Error::SessionNotMaterialized
|
|
269
|
-
end
|
|
266
|
+
raise Error::SessionNotMaterialized unless materialized?
|
|
270
267
|
|
|
271
268
|
@server_session.session_id
|
|
272
269
|
end
|
|
@@ -294,20 +291,20 @@ module Mongo
|
|
|
294
291
|
#
|
|
295
292
|
# @since 2.5.0
|
|
296
293
|
MISMATCHED_CLUSTER_ERROR_MSG = 'The configuration of the client used to create this session does not match that ' +
|
|
297
|
-
|
|
298
|
-
|
|
294
|
+
'of the client owning this operation. Please only use this session for operations through its parent ' +
|
|
295
|
+
'client.'
|
|
299
296
|
|
|
300
297
|
# Error message describing that the session cannot be used because it has already been ended.
|
|
301
298
|
#
|
|
302
299
|
# @since 2.5.0
|
|
303
|
-
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.'
|
|
304
301
|
|
|
305
302
|
# Error message describing that sessions are not supported by the server version.
|
|
306
303
|
#
|
|
307
304
|
# @since 2.5.0
|
|
308
305
|
# @deprecated
|
|
309
|
-
SESSIONS_NOT_SUPPORTED = 'Sessions are not supported by the connected servers.'
|
|
310
|
-
#
|
|
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
|
|
311
308
|
|
|
312
309
|
# The state of a session in which the last operation was not related to
|
|
313
310
|
# any transaction or no operations have yet occurred.
|
|
@@ -382,13 +379,15 @@ module Mongo
|
|
|
382
379
|
rescue Mongo::Error, Error::AuthError
|
|
383
380
|
end
|
|
384
381
|
end
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
|
388
386
|
end
|
|
389
387
|
ensure
|
|
390
388
|
@server_session = nil
|
|
391
389
|
@ended = true
|
|
390
|
+
@client = nil
|
|
392
391
|
end
|
|
393
392
|
|
|
394
393
|
# Executes the provided block in a transaction, retrying as necessary.
|
|
@@ -446,44 +445,74 @@ module Mongo
|
|
|
446
445
|
#
|
|
447
446
|
# @since 2.7.0
|
|
448
447
|
def with_transaction(options = nil)
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
@with_transaction_deadline = deadline
|
|
460
|
-
else
|
|
461
|
-
deadline = Utils.monotonic_time + 120
|
|
462
|
-
end
|
|
448
|
+
@inside_with_transaction = true
|
|
449
|
+
@with_transaction_timeout_ms = options&.dig(:timeout_ms) || @options[:default_timeout_ms] || @client.timeout_ms
|
|
450
|
+
@with_transaction_deadline = calculate_with_transaction_deadline(options)
|
|
451
|
+
deadline = if @with_transaction_deadline
|
|
452
|
+
# CSOT enabled, so we have a customer defined deadline.
|
|
453
|
+
@with_transaction_deadline
|
|
454
|
+
else
|
|
455
|
+
# CSOT not enabled, so we use the default deadline, 120 seconds.
|
|
456
|
+
Utils.monotonic_time + 120
|
|
457
|
+
end
|
|
463
458
|
transaction_in_progress = false
|
|
459
|
+
transaction_attempt = 0
|
|
460
|
+
last_error = nil
|
|
461
|
+
overload_error_count = 0
|
|
462
|
+
overload_encountered = false
|
|
463
|
+
|
|
464
464
|
loop do
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
|
468
482
|
end
|
|
483
|
+
|
|
484
|
+
commit_options = {}
|
|
485
|
+
commit_options[:write_concern] = options[:write_concern] if options
|
|
469
486
|
start_transaction(options)
|
|
470
487
|
transaction_in_progress = true
|
|
488
|
+
transaction_attempt += 1
|
|
489
|
+
|
|
471
490
|
begin
|
|
472
491
|
rv = yield self
|
|
473
492
|
rescue Exception => e
|
|
474
493
|
if within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
|
|
475
494
|
log_warn("Aborting transaction due to #{e.class}: #{e}")
|
|
476
|
-
|
|
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)
|
|
477
499
|
abort_transaction
|
|
478
500
|
transaction_in_progress = false
|
|
479
501
|
end
|
|
480
502
|
|
|
481
|
-
if
|
|
503
|
+
if deadline_expired?(deadline)
|
|
482
504
|
transaction_in_progress = false
|
|
483
|
-
|
|
505
|
+
make_timeout_error_from(e, 'CSOT timeout expired during withTransaction callback')
|
|
484
506
|
end
|
|
485
507
|
|
|
486
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
|
|
487
516
|
next
|
|
488
517
|
end
|
|
489
518
|
|
|
@@ -494,32 +523,71 @@ module Mongo
|
|
|
494
523
|
return rv
|
|
495
524
|
end
|
|
496
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
|
+
|
|
497
535
|
begin
|
|
498
536
|
commit_transaction(commit_options)
|
|
499
537
|
transaction_in_progress = false
|
|
500
538
|
return rv
|
|
501
539
|
rescue Mongo::Error => e
|
|
502
540
|
if e.label?('UnknownTransactionCommitResult')
|
|
503
|
-
if
|
|
504
|
-
|
|
505
|
-
then
|
|
541
|
+
if deadline_expired?(deadline) ||
|
|
542
|
+
(e.is_a?(Error::OperationFailure::Family) && e.max_time_ms_expired?)
|
|
506
543
|
transaction_in_progress = false
|
|
507
|
-
|
|
544
|
+
|
|
545
|
+
raise unless @with_transaction_timeout_ms && deadline_expired?(deadline)
|
|
546
|
+
|
|
547
|
+
make_timeout_error_from(e, 'CSOT timeout expired during withTransaction commit')
|
|
508
548
|
end
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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')
|
|
562
|
+
end
|
|
563
|
+
unless @client.retry_policy.should_retry_overload?(overload_error_count, delay)
|
|
564
|
+
transaction_in_progress = false
|
|
565
|
+
raise
|
|
516
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
|
|
517
578
|
commit_options[:write_concern] = wc_options.merge(w: :majority)
|
|
518
579
|
retry
|
|
519
580
|
elsif e.label?('TransientTransactionError')
|
|
520
581
|
if Utils.monotonic_time >= deadline
|
|
521
582
|
transaction_in_progress = false
|
|
522
|
-
|
|
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
|
|
523
591
|
end
|
|
524
592
|
@state = NO_TRANSACTION_STATE
|
|
525
593
|
next
|
|
@@ -546,6 +614,8 @@ module Mongo
|
|
|
546
614
|
end
|
|
547
615
|
end
|
|
548
616
|
@with_transaction_deadline = nil
|
|
617
|
+
@with_transaction_timeout_ms = nil
|
|
618
|
+
@inside_with_transaction = false
|
|
549
619
|
end
|
|
550
620
|
|
|
551
621
|
# Places subsequent operations in this session into a new transaction.
|
|
@@ -560,7 +630,7 @@ module Mongo
|
|
|
560
630
|
#
|
|
561
631
|
# @option options [ Integer ] :max_commit_time_ms The maximum amount of
|
|
562
632
|
# time to allow a single commitTransaction command to run, in milliseconds.
|
|
563
|
-
# This
|
|
633
|
+
# This option is deprecated, use :timeout_ms instead.
|
|
564
634
|
# @option options [ Hash ] :read_concern The read concern options hash,
|
|
565
635
|
# with the following optional keys:
|
|
566
636
|
# - *:level* -- the read preference level as a symbol; valid values
|
|
@@ -586,28 +656,25 @@ module Mongo
|
|
|
586
656
|
if options
|
|
587
657
|
Lint.validate_read_concern_option(options[:read_concern])
|
|
588
658
|
|
|
589
|
-
|
|
590
|
-
#
|
|
591
|
-
#
|
|
592
|
-
#
|
|
593
|
-
mode
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
end
|
|
599
|
-
=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
|
|
600
668
|
end
|
|
601
669
|
|
|
602
|
-
if snapshot?
|
|
603
|
-
raise Mongo::Error::SnapshotSessionTransactionProhibited
|
|
604
|
-
end
|
|
670
|
+
raise Mongo::Error::SnapshotSessionTransactionProhibited if snapshot?
|
|
605
671
|
|
|
606
672
|
check_if_ended!
|
|
607
673
|
|
|
608
674
|
if within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
|
|
609
675
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
610
|
-
Mongo::Error::InvalidTransactionOperation::TRANSACTION_ALREADY_IN_PROGRESS
|
|
676
|
+
Mongo::Error::InvalidTransactionOperation::TRANSACTION_ALREADY_IN_PROGRESS
|
|
677
|
+
)
|
|
611
678
|
end
|
|
612
679
|
|
|
613
680
|
unpin
|
|
@@ -617,11 +684,13 @@ module Mongo
|
|
|
617
684
|
|
|
618
685
|
if txn_write_concern && !WriteConcern.get(txn_write_concern).acknowledged?
|
|
619
686
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
620
|
-
Mongo::Error::InvalidTransactionOperation::UNACKNOWLEDGED_WRITE_CONCERN
|
|
687
|
+
Mongo::Error::InvalidTransactionOperation::UNACKNOWLEDGED_WRITE_CONCERN
|
|
688
|
+
)
|
|
621
689
|
end
|
|
622
690
|
|
|
623
691
|
@state = STARTING_TRANSACTION_STATE
|
|
624
692
|
@already_committed = false
|
|
693
|
+
tracer.start_transaction_span(self)
|
|
625
694
|
|
|
626
695
|
# This method has no explicit return value.
|
|
627
696
|
# We could return nil here but true indicates to the user that the
|
|
@@ -645,7 +714,7 @@ module Mongo
|
|
|
645
714
|
# @raise [ Error::InvalidTransactionOperation ] If there is no active transaction.
|
|
646
715
|
#
|
|
647
716
|
# @since 2.6.0
|
|
648
|
-
def commit_transaction(options=nil)
|
|
717
|
+
def commit_transaction(options = nil)
|
|
649
718
|
QueryCache.clear
|
|
650
719
|
check_if_ended!
|
|
651
720
|
check_if_no_transaction!
|
|
@@ -653,7 +722,9 @@ module Mongo
|
|
|
653
722
|
if within_states?(TRANSACTION_ABORTED_STATE)
|
|
654
723
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
655
724
|
Mongo::Error::InvalidTransactionOperation.cannot_call_after_msg(
|
|
656
|
-
:abortTransaction, :commitTransaction
|
|
725
|
+
:abortTransaction, :commitTransaction
|
|
726
|
+
)
|
|
727
|
+
)
|
|
657
728
|
end
|
|
658
729
|
|
|
659
730
|
options ||= {}
|
|
@@ -673,9 +744,7 @@ module Mongo
|
|
|
673
744
|
@committing_transaction = true
|
|
674
745
|
|
|
675
746
|
write_concern = options[:write_concern] || txn_options[:write_concern]
|
|
676
|
-
if write_concern && !write_concern.is_a?(WriteConcern::Base)
|
|
677
|
-
write_concern = WriteConcern.get(write_concern)
|
|
678
|
-
end
|
|
747
|
+
write_concern = WriteConcern.get(write_concern) if write_concern && !write_concern.is_a?(WriteConcern::Base)
|
|
679
748
|
|
|
680
749
|
context = Operation::Context.new(
|
|
681
750
|
client: @client,
|
|
@@ -683,15 +752,14 @@ module Mongo
|
|
|
683
752
|
operation_timeouts: operation_timeouts(options)
|
|
684
753
|
)
|
|
685
754
|
write_with_retry(write_concern, ending_transaction: true,
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
if context.retry?
|
|
755
|
+
context: context) do |connection, txn_num, context|
|
|
756
|
+
if context.retry? && !context.overload_only_retry?
|
|
689
757
|
if write_concern
|
|
690
758
|
wco = write_concern.options.merge(w: :majority)
|
|
691
|
-
wco[:wtimeout] ||=
|
|
759
|
+
wco[:wtimeout] ||= 10_000
|
|
692
760
|
write_concern = WriteConcern.get(wco)
|
|
693
761
|
else
|
|
694
|
-
write_concern = WriteConcern.get(w: :majority, wtimeout:
|
|
762
|
+
write_concern = WriteConcern.get(w: :majority, wtimeout: 10_000)
|
|
695
763
|
end
|
|
696
764
|
end
|
|
697
765
|
spec = {
|
|
@@ -701,9 +769,14 @@ module Mongo
|
|
|
701
769
|
txn_num: txn_num,
|
|
702
770
|
write_concern: write_concern,
|
|
703
771
|
}
|
|
704
|
-
Operation::Command.new(spec)
|
|
772
|
+
operation = Operation::Command.new(spec)
|
|
773
|
+
tracer.trace_operation(operation, context, op_name: 'commitTransaction') do
|
|
774
|
+
operation.execute_with_connection(connection, context: context)
|
|
775
|
+
end
|
|
705
776
|
end
|
|
706
777
|
end
|
|
778
|
+
# Finish the transaction span before changing state
|
|
779
|
+
tracer.finish_transaction_span(self)
|
|
707
780
|
ensure
|
|
708
781
|
@state = TRANSACTION_COMMITTED_STATE
|
|
709
782
|
@committing_transaction = false
|
|
@@ -736,12 +809,15 @@ module Mongo
|
|
|
736
809
|
if within_states?(TRANSACTION_COMMITTED_STATE)
|
|
737
810
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
738
811
|
Mongo::Error::InvalidTransactionOperation.cannot_call_after_msg(
|
|
739
|
-
:commitTransaction, :abortTransaction
|
|
812
|
+
:commitTransaction, :abortTransaction
|
|
813
|
+
)
|
|
814
|
+
)
|
|
740
815
|
end
|
|
741
816
|
|
|
742
817
|
if within_states?(TRANSACTION_ABORTED_STATE)
|
|
743
818
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
744
|
-
Mongo::Error::InvalidTransactionOperation.cannot_call_twice_msg(:abortTransaction)
|
|
819
|
+
Mongo::Error::InvalidTransactionOperation.cannot_call_twice_msg(:abortTransaction)
|
|
820
|
+
)
|
|
745
821
|
end
|
|
746
822
|
|
|
747
823
|
options ||= {}
|
|
@@ -755,27 +831,31 @@ module Mongo
|
|
|
755
831
|
operation_timeouts: operation_timeouts(options)
|
|
756
832
|
)
|
|
757
833
|
write_with_retry(txn_options[:write_concern],
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
ensure
|
|
768
|
-
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)
|
|
769
843
|
end
|
|
844
|
+
ensure
|
|
845
|
+
unpin
|
|
770
846
|
end
|
|
771
847
|
end
|
|
772
848
|
|
|
849
|
+
# Finish the transaction span before changing state
|
|
850
|
+
tracer.finish_transaction_span(self)
|
|
773
851
|
@state = TRANSACTION_ABORTED_STATE
|
|
774
852
|
rescue Mongo::Error::InvalidTransactionOperation
|
|
775
853
|
raise
|
|
776
854
|
rescue Mongo::Error
|
|
855
|
+
tracer.finish_transaction_span(self)
|
|
777
856
|
@state = TRANSACTION_ABORTED_STATE
|
|
778
857
|
rescue Exception
|
|
858
|
+
tracer.finish_transaction_span(self)
|
|
779
859
|
@state = TRANSACTION_ABORTED_STATE
|
|
780
860
|
raise
|
|
781
861
|
ensure
|
|
@@ -826,14 +906,12 @@ module Mongo
|
|
|
826
906
|
#
|
|
827
907
|
# @api private
|
|
828
908
|
def pin_to_server(server)
|
|
829
|
-
if server.nil?
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
unless server.mongos?
|
|
834
|
-
raise Error::LintError, "Attempted to pin the session to server #{server.summary} which is not a mongos"
|
|
835
|
-
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"
|
|
836
913
|
end
|
|
914
|
+
|
|
837
915
|
@pinned_server = server
|
|
838
916
|
end
|
|
839
917
|
|
|
@@ -841,13 +919,14 @@ module Mongo
|
|
|
841
919
|
#
|
|
842
920
|
# @param [ Integer ] connection_global_id The global id of connection to pin
|
|
843
921
|
# this session to.
|
|
922
|
+
# @param [ Connection | nil ] connection The connection object to pin to.
|
|
844
923
|
#
|
|
845
924
|
# @api private
|
|
846
|
-
def pin_to_connection(connection_global_id)
|
|
847
|
-
if connection_global_id.nil?
|
|
848
|
-
|
|
849
|
-
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
|
+
|
|
850
928
|
@pinned_connection_global_id = connection_global_id
|
|
929
|
+
@pinned_connection = connection
|
|
851
930
|
end
|
|
852
931
|
|
|
853
932
|
# Unpins this session from the pinned server or connection,
|
|
@@ -859,7 +938,16 @@ module Mongo
|
|
|
859
938
|
def unpin(connection = nil)
|
|
860
939
|
@pinned_server = nil
|
|
861
940
|
@pinned_connection_global_id = nil
|
|
862
|
-
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
|
|
863
951
|
end
|
|
864
952
|
|
|
865
953
|
# Unpins this session from the pinned server or connection, if the session was pinned
|
|
@@ -875,14 +963,12 @@ module Mongo
|
|
|
875
963
|
# @api private
|
|
876
964
|
def unpin_maybe(error, connection = nil)
|
|
877
965
|
if !within_states?(Session::NO_TRANSACTION_STATE) &&
|
|
878
|
-
|
|
879
|
-
then
|
|
966
|
+
error.label?('TransientTransactionError')
|
|
880
967
|
unpin(connection)
|
|
881
968
|
end
|
|
882
969
|
|
|
883
970
|
if committing_transaction? &&
|
|
884
|
-
|
|
885
|
-
then
|
|
971
|
+
error.label?('UnknownTransactionCommitResult')
|
|
886
972
|
unpin(connection)
|
|
887
973
|
end
|
|
888
974
|
end
|
|
@@ -913,9 +999,7 @@ module Mongo
|
|
|
913
999
|
# @api private
|
|
914
1000
|
def add_start_transaction!(command)
|
|
915
1001
|
command.tap do |c|
|
|
916
|
-
if starting_transaction?
|
|
917
|
-
c[:startTransaction] = true
|
|
918
|
-
end
|
|
1002
|
+
c[:startTransaction] = true if starting_transaction?
|
|
919
1003
|
end
|
|
920
1004
|
end
|
|
921
1005
|
|
|
@@ -943,7 +1027,7 @@ module Mongo
|
|
|
943
1027
|
#
|
|
944
1028
|
# @since 2.6.0
|
|
945
1029
|
# @api private
|
|
946
|
-
def add_txn_opts!(command,
|
|
1030
|
+
def add_txn_opts!(command, _read, context)
|
|
947
1031
|
command.tap do |c|
|
|
948
1032
|
# The read concern should be added to any command that starts a transaction.
|
|
949
1033
|
if starting_transaction?
|
|
@@ -966,27 +1050,23 @@ module Mongo
|
|
|
966
1050
|
if rc.nil? || rc.empty?
|
|
967
1051
|
c.delete(:readConcern)
|
|
968
1052
|
else
|
|
969
|
-
c[:readConcern
|
|
1053
|
+
c[:readConcern] = Options::Mapper.transform_values_to_strings(rc)
|
|
970
1054
|
end
|
|
971
1055
|
end
|
|
972
1056
|
|
|
973
1057
|
# We need to send the read concern level as a string rather than a symbol.
|
|
974
|
-
if c[:readConcern]
|
|
975
|
-
c[:readConcern] = Options::Mapper.transform_values_to_strings(c[:readConcern])
|
|
976
|
-
end
|
|
1058
|
+
c[:readConcern] = Options::Mapper.transform_values_to_strings(c[:readConcern]) if c[:readConcern]
|
|
977
1059
|
|
|
978
|
-
if c[:commitTransaction]
|
|
979
|
-
|
|
980
|
-
c[:maxTimeMS] = max_time_ms
|
|
981
|
-
end
|
|
1060
|
+
if c[:commitTransaction] && (max_time_ms = txn_options[:max_commit_time_ms])
|
|
1061
|
+
c[:maxTimeMS] = max_time_ms
|
|
982
1062
|
end
|
|
983
1063
|
|
|
984
1064
|
# The write concern should be added to any abortTransaction or commitTransaction command.
|
|
985
|
-
if
|
|
1065
|
+
if c[:abortTransaction] || c[:commitTransaction]
|
|
986
1066
|
if @already_committed
|
|
987
1067
|
wc = BSON::Document.new(c[:writeConcern] || txn_write_concern || {})
|
|
988
1068
|
wc.merge!(w: :majority)
|
|
989
|
-
wc[:wtimeout] ||=
|
|
1069
|
+
wc[:wtimeout] ||= 10_000
|
|
990
1070
|
c[:writeConcern] = wc
|
|
991
1071
|
elsif txn_write_concern
|
|
992
1072
|
c[:writeConcern] ||= txn_write_concern
|
|
@@ -999,12 +1079,10 @@ module Mongo
|
|
|
999
1079
|
end
|
|
1000
1080
|
|
|
1001
1081
|
# Ignore wtimeout if csot
|
|
1002
|
-
if context&.csot?
|
|
1003
|
-
c[:writeConcern]&.delete(:wtimeout)
|
|
1004
|
-
end
|
|
1082
|
+
c[:writeConcern]&.delete(:wtimeout) if context&.csot?
|
|
1005
1083
|
|
|
1006
1084
|
# We must not send an empty (server default) write concern.
|
|
1007
|
-
c.delete(:writeConcern) if c[:writeConcern]
|
|
1085
|
+
c.delete(:writeConcern) if c[:writeConcern] && c[:writeConcern].empty?
|
|
1008
1086
|
end
|
|
1009
1087
|
end
|
|
1010
1088
|
|
|
@@ -1026,7 +1104,7 @@ module Mongo
|
|
|
1026
1104
|
end
|
|
1027
1105
|
end
|
|
1028
1106
|
|
|
1029
|
-
# Ensure that the read preference of a command primary.
|
|
1107
|
+
# Ensure that the read preference of a command is primary.
|
|
1030
1108
|
#
|
|
1031
1109
|
# @example
|
|
1032
1110
|
# session.validate_read_preference!(command)
|
|
@@ -1042,11 +1120,21 @@ module Mongo
|
|
|
1042
1120
|
|
|
1043
1121
|
mode = command['$readPreference']['mode'] || command['$readPreference'][:mode]
|
|
1044
1122
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
)
|
|
1049
|
-
|
|
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
|
|
1050
1138
|
end
|
|
1051
1139
|
|
|
1052
1140
|
# Update the state of the session due to a (non-commit and non-abort) operation being run.
|
|
@@ -1076,8 +1164,8 @@ module Mongo
|
|
|
1076
1164
|
# @since 2.5.0
|
|
1077
1165
|
# @api private
|
|
1078
1166
|
def validate!(client)
|
|
1079
|
-
check_matching_cluster!(client)
|
|
1080
1167
|
check_if_ended!
|
|
1168
|
+
check_matching_cluster!(client)
|
|
1081
1169
|
self
|
|
1082
1170
|
end
|
|
1083
1171
|
|
|
@@ -1101,10 +1189,8 @@ module Mongo
|
|
|
1101
1189
|
end
|
|
1102
1190
|
@server_session.set_last_use!
|
|
1103
1191
|
|
|
1104
|
-
if doc = result.reply && result.reply.documents.first
|
|
1105
|
-
|
|
1106
|
-
self.recovery_token = doc[:recoveryToken]
|
|
1107
|
-
end
|
|
1192
|
+
if (doc = result.reply && result.reply.documents.first) && doc[:recoveryToken]
|
|
1193
|
+
self.recovery_token = doc[:recoveryToken]
|
|
1108
1194
|
end
|
|
1109
1195
|
|
|
1110
1196
|
result
|
|
@@ -1121,11 +1207,11 @@ module Mongo
|
|
|
1121
1207
|
#
|
|
1122
1208
|
# @since 2.5.0
|
|
1123
1209
|
def advance_operation_time(new_operation_time)
|
|
1124
|
-
if @operation_time
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1210
|
+
@operation_time = if @operation_time
|
|
1211
|
+
[ @operation_time, new_operation_time ].max
|
|
1212
|
+
else
|
|
1213
|
+
new_operation_time
|
|
1214
|
+
end
|
|
1129
1215
|
end
|
|
1130
1216
|
|
|
1131
1217
|
# If not already set, populate a session objects's server_session by
|
|
@@ -1135,9 +1221,7 @@ module Mongo
|
|
|
1135
1221
|
#
|
|
1136
1222
|
# @api private
|
|
1137
1223
|
def materialize_if_needed
|
|
1138
|
-
if ended?
|
|
1139
|
-
raise Error::SessionEnded
|
|
1140
|
-
end
|
|
1224
|
+
raise Error::SessionEnded if ended?
|
|
1141
1225
|
|
|
1142
1226
|
return unless implicit? && !@server_session
|
|
1143
1227
|
|
|
@@ -1148,9 +1232,7 @@ module Mongo
|
|
|
1148
1232
|
|
|
1149
1233
|
# @api private
|
|
1150
1234
|
def materialized?
|
|
1151
|
-
if ended?
|
|
1152
|
-
raise Error::SessionEnded
|
|
1153
|
-
end
|
|
1235
|
+
raise Error::SessionEnded if ended?
|
|
1154
1236
|
|
|
1155
1237
|
!@server_session.nil?
|
|
1156
1238
|
end
|
|
@@ -1165,9 +1247,7 @@ module Mongo
|
|
|
1165
1247
|
# @since 2.5.0
|
|
1166
1248
|
# @api private
|
|
1167
1249
|
def next_txn_num
|
|
1168
|
-
if ended?
|
|
1169
|
-
raise Error::SessionEnded
|
|
1170
|
-
end
|
|
1250
|
+
raise Error::SessionEnded if ended?
|
|
1171
1251
|
|
|
1172
1252
|
@server_session.next_txn_num
|
|
1173
1253
|
end
|
|
@@ -1181,9 +1261,7 @@ module Mongo
|
|
|
1181
1261
|
#
|
|
1182
1262
|
# @since 2.6.0
|
|
1183
1263
|
def txn_num
|
|
1184
|
-
if ended?
|
|
1185
|
-
raise Error::SessionEnded
|
|
1186
|
-
end
|
|
1264
|
+
raise Error::SessionEnded if ended?
|
|
1187
1265
|
|
|
1188
1266
|
@server_session.txn_num
|
|
1189
1267
|
end
|
|
@@ -1191,8 +1269,16 @@ module Mongo
|
|
|
1191
1269
|
# @api private
|
|
1192
1270
|
attr_accessor :snapshot_timestamp
|
|
1193
1271
|
|
|
1272
|
+
# @return [ Integer | nil ] The deadline for the current transaction, if any.
|
|
1273
|
+
# @api private
|
|
1194
1274
|
attr_reader :with_transaction_deadline
|
|
1195
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
|
+
|
|
1196
1282
|
private
|
|
1197
1283
|
|
|
1198
1284
|
# Get the read concern the session will use when starting a transaction.
|
|
@@ -1218,7 +1304,8 @@ module Mongo
|
|
|
1218
1304
|
return unless within_states?(NO_TRANSACTION_STATE)
|
|
1219
1305
|
|
|
1220
1306
|
raise Mongo::Error::InvalidTransactionOperation.new(
|
|
1221
|
-
Mongo::Error::InvalidTransactionOperation::NO_TRANSACTION_STARTED
|
|
1307
|
+
Mongo::Error::InvalidTransactionOperation::NO_TRANSACTION_STARTED
|
|
1308
|
+
)
|
|
1222
1309
|
end
|
|
1223
1310
|
|
|
1224
1311
|
def txn_write_concern
|
|
@@ -1229,25 +1316,23 @@ module Mongo
|
|
|
1229
1316
|
# Returns causal consistency document if the last operation time is
|
|
1230
1317
|
# known and causal consistency is enabled, otherwise returns nil.
|
|
1231
1318
|
def causal_consistency_doc
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
nil
|
|
1236
|
-
end
|
|
1319
|
+
return unless operation_time && causal_consistency?
|
|
1320
|
+
|
|
1321
|
+
{ afterClusterTime: operation_time }
|
|
1237
1322
|
end
|
|
1238
1323
|
|
|
1239
1324
|
def causal_consistency?
|
|
1240
|
-
@causal_consistency ||=
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1325
|
+
@causal_consistency ||= if @options.key?(:causal_consistency)
|
|
1326
|
+
!!@options[:causal_consistency]
|
|
1327
|
+
else
|
|
1328
|
+
true
|
|
1329
|
+
end
|
|
1245
1330
|
end
|
|
1246
1331
|
|
|
1247
1332
|
def set_operation_time(result)
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1333
|
+
return unless result && result.operation_time
|
|
1334
|
+
|
|
1335
|
+
@operation_time = result.operation_time
|
|
1251
1336
|
end
|
|
1252
1337
|
|
|
1253
1338
|
def check_if_ended!
|
|
@@ -1255,36 +1340,86 @@ module Mongo
|
|
|
1255
1340
|
end
|
|
1256
1341
|
|
|
1257
1342
|
def check_matching_cluster!(client)
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1343
|
+
return unless cluster != client.cluster
|
|
1344
|
+
|
|
1345
|
+
raise Mongo::Error::InvalidSession.new(MISMATCHED_CLUSTER_ERROR_MSG)
|
|
1261
1346
|
end
|
|
1262
1347
|
|
|
1263
1348
|
def check_transactions_supported!
|
|
1264
|
-
raise Mongo::Error::TransactionsNotSupported,
|
|
1265
|
-
|
|
1266
|
-
cluster.next_primary.with_connection do |conn|
|
|
1267
|
-
if cluster.replica_set? && !conn.features.transactions_enabled?
|
|
1268
|
-
raise Mongo::Error::TransactionsNotSupported, "server version is < 4.0"
|
|
1269
|
-
end
|
|
1270
|
-
if cluster.sharded? && !conn.features.sharded_transactions_enabled?
|
|
1271
|
-
raise Mongo::Error::TransactionsNotSupported, "sharded transactions require server version >= 4.2"
|
|
1272
|
-
end
|
|
1273
|
-
end
|
|
1349
|
+
raise Mongo::Error::TransactionsNotSupported, 'standalone topology' if cluster.single?
|
|
1274
1350
|
end
|
|
1275
1351
|
|
|
1276
1352
|
def operation_timeouts(opts)
|
|
1277
1353
|
{
|
|
1278
|
-
inherited_timeout_ms: @client.timeout_ms
|
|
1354
|
+
inherited_timeout_ms: @with_transaction_timeout_ms || @client.timeout_ms
|
|
1279
1355
|
}.tap do |result|
|
|
1280
|
-
if @
|
|
1281
|
-
if
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
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'
|
|
1285
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
|
|
1365
|
+
end
|
|
1366
|
+
end
|
|
1367
|
+
end
|
|
1368
|
+
|
|
1369
|
+
def calculate_with_transaction_deadline(opts)
|
|
1370
|
+
calc = lambda { |timeout|
|
|
1371
|
+
if timeout == 0
|
|
1372
|
+
0
|
|
1373
|
+
else
|
|
1374
|
+
Utils.monotonic_time + (timeout / 1000.0)
|
|
1375
|
+
end
|
|
1376
|
+
}
|
|
1377
|
+
if timeout_ms = opts&.dig(:timeout_ms)
|
|
1378
|
+
calc.call(timeout_ms)
|
|
1379
|
+
elsif default_timeout_ms = @options[:default_timeout_ms]
|
|
1380
|
+
calc.call(default_timeout_ms)
|
|
1381
|
+
elsif @client.timeout_ms
|
|
1382
|
+
calc.call(@client.timeout_ms)
|
|
1383
|
+
end
|
|
1384
|
+
end
|
|
1385
|
+
|
|
1386
|
+
def deadline_expired?(deadline)
|
|
1387
|
+
if deadline.zero?
|
|
1388
|
+
false
|
|
1389
|
+
else
|
|
1390
|
+
Utils.monotonic_time >= deadline
|
|
1391
|
+
end
|
|
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) }
|
|
1286
1418
|
end
|
|
1419
|
+
raise timeout_error
|
|
1287
1420
|
end
|
|
1421
|
+
|
|
1422
|
+
raise last_error
|
|
1288
1423
|
end
|
|
1289
1424
|
end
|
|
1290
1425
|
end
|