mongo 2.5.3 → 2.6.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/LICENSE +1 -1
- data/README.md +3 -2
- data/lib/mongo.rb +2 -2
- data/lib/mongo/address.rb +10 -2
- data/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +26 -5
- data/lib/mongo/address/unix.rb +1 -1
- data/lib/mongo/auth.rb +10 -3
- data/lib/mongo/auth/cr.rb +4 -1
- data/lib/mongo/auth/cr/conversation.rb +4 -1
- data/lib/mongo/auth/ldap.rb +1 -1
- data/lib/mongo/auth/ldap/conversation.rb +1 -1
- data/lib/mongo/auth/roles.rb +1 -1
- data/lib/mongo/auth/scram.rb +24 -7
- data/lib/mongo/auth/scram/conversation.rb +52 -19
- data/lib/mongo/auth/stringprep.rb +114 -0
- data/lib/mongo/auth/stringprep/profiles/sasl.rb +73 -0
- data/lib/mongo/auth/stringprep/tables.rb +3232 -0
- data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +174 -0
- data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +1170 -0
- data/lib/mongo/auth/user.rb +14 -3
- data/lib/mongo/auth/user/view.rb +1 -1
- data/lib/mongo/auth/x509.rb +1 -1
- data/lib/mongo/auth/x509/conversation.rb +1 -1
- data/lib/mongo/bson.rb +1 -1
- data/lib/mongo/bulk_write.rb +8 -8
- data/lib/mongo/bulk_write/combineable.rb +1 -1
- data/lib/mongo/bulk_write/ordered_combiner.rb +1 -1
- data/lib/mongo/bulk_write/result.rb +1 -1
- data/lib/mongo/bulk_write/result_combiner.rb +4 -4
- data/lib/mongo/bulk_write/transformable.rb +1 -1
- data/lib/mongo/bulk_write/unordered_combiner.rb +1 -1
- data/lib/mongo/bulk_write/validatable.rb +1 -1
- data/lib/mongo/client.rb +115 -24
- data/lib/mongo/cluster.rb +17 -10
- data/lib/mongo/cluster/app_metadata.rb +7 -1
- data/lib/mongo/cluster/periodic_executor.rb +1 -1
- data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -1
- data/lib/mongo/cluster/topology.rb +12 -2
- data/lib/mongo/cluster/topology/replica_set.rb +9 -1
- data/lib/mongo/cluster/topology/sharded.rb +1 -1
- data/lib/mongo/cluster/topology/single.rb +1 -1
- data/lib/mongo/cluster/topology/unknown.rb +1 -1
- data/lib/mongo/collection.rb +75 -19
- data/lib/mongo/collection/view.rb +1 -1
- data/lib/mongo/collection/view/aggregation.rb +1 -1
- data/lib/mongo/collection/view/builder.rb +1 -1
- data/lib/mongo/collection/view/builder/aggregation.rb +3 -3
- data/lib/mongo/collection/view/builder/find_command.rb +1 -1
- data/lib/mongo/collection/view/builder/flags.rb +1 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/builder/modifiers.rb +1 -1
- data/lib/mongo/collection/view/builder/op_query.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +193 -17
- data/lib/mongo/collection/view/change_stream/retryable.rb +3 -20
- data/lib/mongo/collection/view/explainable.rb +1 -1
- data/lib/mongo/collection/view/immutable.rb +1 -1
- data/lib/mongo/collection/view/iterable.rb +2 -2
- data/lib/mongo/collection/view/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/readable.rb +108 -29
- data/lib/mongo/collection/view/writable.rb +3 -3
- data/lib/mongo/cursor.rb +44 -4
- data/lib/mongo/cursor/builder.rb +1 -1
- data/lib/mongo/cursor/builder/get_more_command.rb +1 -1
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +1 -1
- data/lib/mongo/cursor/builder/op_get_more.rb +1 -1
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +1 -1
- data/lib/mongo/database.rb +46 -3
- data/lib/mongo/database/view.rb +11 -11
- data/lib/mongo/dbref.rb +1 -1
- data/lib/mongo/error.rb +57 -1
- data/lib/mongo/error/bulk_write_error.rb +2 -2
- data/lib/mongo/error/change_stream_resumable.rb +37 -0
- data/lib/mongo/error/closed_stream.rb +1 -1
- data/lib/mongo/error/extra_file_chunk.rb +1 -1
- data/lib/mongo/error/failed_stringprep_validation.rb +38 -0
- data/lib/mongo/error/file_not_found.rb +1 -1
- data/lib/mongo/error/insufficient_iteration_count.rb +38 -0
- data/lib/mongo/error/invalid_application_name.rb +1 -1
- data/lib/mongo/error/invalid_bulk_operation.rb +1 -1
- data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -1
- data/lib/mongo/error/invalid_collection_name.rb +1 -1
- data/lib/mongo/error/invalid_database_name.rb +1 -1
- data/lib/mongo/error/invalid_document.rb +1 -1
- data/lib/mongo/error/invalid_file.rb +1 -1
- data/lib/mongo/error/invalid_file_revision.rb +1 -1
- data/lib/mongo/error/invalid_min_pool_size.rb +1 -1
- data/lib/mongo/error/invalid_nonce.rb +1 -1
- data/lib/mongo/error/invalid_read_option.rb +35 -0
- data/lib/mongo/error/invalid_replacement_document.rb +1 -1
- data/lib/mongo/error/invalid_server_preference.rb +1 -1
- data/lib/mongo/error/invalid_session.rb +1 -1
- data/lib/mongo/error/invalid_signature.rb +1 -1
- data/lib/mongo/error/invalid_transaction_operation.rb +82 -0
- data/lib/mongo/error/invalid_txt_record.rb +1 -1
- data/lib/mongo/error/invalid_update_document.rb +1 -1
- data/lib/mongo/error/invalid_uri.rb +1 -1
- data/lib/mongo/error/invalid_write_concern.rb +1 -1
- data/lib/mongo/error/max_bson_size.rb +1 -1
- data/lib/mongo/error/max_message_size.rb +1 -1
- data/lib/mongo/error/mismatched_domain.rb +1 -1
- data/lib/mongo/error/missing_file_chunk.rb +1 -1
- data/lib/mongo/error/missing_resume_token.rb +1 -1
- data/lib/mongo/error/multi_index_drop.rb +1 -1
- data/lib/mongo/error/need_primary_server.rb +1 -1
- data/lib/mongo/error/no_server_available.rb +1 -1
- data/lib/mongo/error/no_srv_records.rb +1 -1
- data/lib/mongo/error/operation_failure.rb +108 -14
- data/lib/mongo/error/parser.rb +50 -1
- data/lib/mongo/error/socket_error.rb +5 -2
- data/lib/mongo/error/socket_timeout_error.rb +5 -2
- data/lib/mongo/error/unchangeable_collection_option.rb +1 -1
- data/lib/mongo/error/unexpected_chunk_length.rb +1 -1
- data/lib/mongo/error/unexpected_response.rb +1 -1
- data/lib/mongo/error/unknown_payload_type.rb +1 -1
- data/lib/mongo/error/unsupported_array_filters.rb +1 -1
- data/lib/mongo/error/unsupported_collation.rb +1 -1
- data/lib/mongo/error/unsupported_features.rb +1 -1
- data/lib/mongo/error/unsupported_message_type.rb +1 -1
- data/lib/mongo/error/write_retryable.rb +27 -0
- data/lib/mongo/event.rb +10 -9
- data/lib/mongo/event/base.rb +33 -0
- data/lib/mongo/event/description_changed.rb +2 -2
- data/lib/mongo/event/listeners.rb +1 -1
- data/lib/mongo/event/member_discovered.rb +4 -2
- data/lib/mongo/event/primary_elected.rb +2 -2
- data/lib/mongo/event/publisher.rb +1 -1
- data/lib/mongo/event/standalone_discovered.rb +2 -2
- data/lib/mongo/event/subscriber.rb +1 -1
- data/lib/mongo/grid.rb +1 -1
- data/lib/mongo/grid/file.rb +1 -1
- data/lib/mongo/grid/file/chunk.rb +3 -3
- data/lib/mongo/grid/file/info.rb +26 -3
- data/lib/mongo/grid/fs_bucket.rb +1 -1
- data/lib/mongo/grid/stream.rb +1 -1
- data/lib/mongo/grid/stream/read.rb +1 -1
- data/lib/mongo/grid/stream/write.rb +1 -1
- data/lib/mongo/index.rb +1 -1
- data/lib/mongo/index/view.rb +1 -1
- data/lib/mongo/loggable.rb +1 -1
- data/lib/mongo/logger.rb +1 -1
- data/lib/mongo/monitoring.rb +99 -62
- data/lib/mongo/monitoring/command_log_subscriber.rb +2 -2
- data/lib/mongo/monitoring/event.rb +2 -1
- data/lib/mongo/monitoring/event/command_failed.rb +19 -6
- data/lib/mongo/monitoring/event/command_started.rb +14 -3
- data/lib/mongo/monitoring/event/command_succeeded.rb +5 -3
- data/lib/mongo/monitoring/event/secure.rb +1 -1
- data/lib/mongo/monitoring/event/server_closed.rb +2 -2
- data/lib/mongo/monitoring/event/server_description_changed.rb +2 -2
- data/lib/mongo/monitoring/event/server_opening.rb +11 -2
- data/lib/mongo/monitoring/event/topology_changed.rb +13 -2
- data/lib/mongo/monitoring/event/topology_closed.rb +2 -2
- data/lib/mongo/monitoring/event/topology_opening.rb +11 -2
- data/lib/mongo/monitoring/publishable.rb +10 -6
- data/lib/mongo/monitoring/sdam_log_subscriber.rb +1 -1
- data/lib/mongo/monitoring/server_closed_log_subscriber.rb +1 -1
- data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +1 -1
- data/lib/mongo/monitoring/server_opening_log_subscriber.rb +1 -1
- data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
- data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +1 -1
- data/lib/mongo/operation/aggregate/op_msg.rb +3 -0
- data/lib/mongo/operation/create/op_msg.rb +9 -0
- data/lib/mongo/operation/create_index/op_msg.rb +9 -0
- data/lib/mongo/operation/create_user/command.rb +1 -1
- data/lib/mongo/operation/create_user/op_msg.rb +10 -1
- data/lib/mongo/operation/delete/op_msg.rb +3 -0
- data/lib/mongo/operation/distinct/op_msg.rb +9 -0
- data/lib/mongo/operation/drop/op_msg.rb +9 -0
- data/lib/mongo/operation/drop_database/op_msg.rb +9 -0
- data/lib/mongo/operation/drop_index/op_msg.rb +9 -0
- data/lib/mongo/operation/explain/op_msg.rb +3 -0
- data/lib/mongo/operation/find/op_msg.rb +3 -0
- data/lib/mongo/operation/get_more.rb +1 -1
- data/lib/mongo/operation/get_more/command.rb +1 -1
- data/lib/mongo/operation/get_more/legacy.rb +1 -1
- data/lib/mongo/operation/get_more/op_msg.rb +3 -0
- data/lib/mongo/operation/indexes/op_msg.rb +3 -0
- data/lib/mongo/operation/indexes/result.rb +1 -1
- data/lib/mongo/operation/insert/bulk_result.rb +32 -2
- data/lib/mongo/operation/insert/op_msg.rb +3 -0
- data/lib/mongo/operation/insert/result.rb +1 -1
- data/lib/mongo/operation/kill_cursors/op_msg.rb +9 -0
- data/lib/mongo/operation/list_collections/op_msg.rb +3 -0
- data/lib/mongo/operation/list_collections/result.rb +5 -1
- data/lib/mongo/operation/map_reduce/op_msg.rb +3 -0
- data/lib/mongo/operation/map_reduce/result.rb +1 -1
- data/lib/mongo/operation/parallel_scan/op_msg.rb +3 -0
- data/lib/mongo/operation/remove_user/op_msg.rb +9 -0
- data/lib/mongo/operation/result.rb +27 -14
- data/lib/mongo/operation/shared/executable.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +78 -7
- data/lib/mongo/operation/shared/specifiable.rb +18 -2
- data/lib/mongo/operation/shared/write_concern_supported.rb +1 -1
- data/lib/mongo/operation/update/op_msg.rb +3 -0
- data/lib/mongo/operation/update_user/command.rb +1 -1
- data/lib/mongo/operation/update_user/op_msg.rb +10 -1
- data/lib/mongo/operation/users_info/op_msg.rb +3 -0
- data/lib/mongo/options.rb +1 -1
- data/lib/mongo/options/mapper.rb +1 -1
- data/lib/mongo/options/redacted.rb +1 -1
- data/lib/mongo/protocol/bit_vector.rb +1 -1
- data/lib/mongo/protocol/compressed.rb +1 -1
- data/lib/mongo/protocol/delete.rb +1 -1
- data/lib/mongo/protocol/get_more.rb +7 -7
- data/lib/mongo/protocol/insert.rb +1 -1
- data/lib/mongo/protocol/kill_cursors.rb +1 -1
- data/lib/mongo/protocol/message.rb +5 -5
- data/lib/mongo/protocol/msg.rb +9 -7
- data/lib/mongo/protocol/query.rb +1 -1
- data/lib/mongo/protocol/registry.rb +1 -1
- data/lib/mongo/protocol/reply.rb +10 -10
- data/lib/mongo/protocol/serializers.rb +1 -1
- data/lib/mongo/protocol/update.rb +1 -1
- data/lib/mongo/retryable.rb +22 -14
- data/lib/mongo/server.rb +1 -1
- data/lib/mongo/server/connectable.rb +1 -1
- data/lib/mongo/server/connection.rb +16 -4
- data/lib/mongo/server/connection_pool.rb +1 -1
- data/lib/mongo/server/connection_pool/queue.rb +1 -1
- data/lib/mongo/server/context.rb +1 -1
- data/lib/mongo/server/description.rb +14 -2
- data/lib/mongo/server/description/features.rb +10 -9
- data/lib/mongo/server/description/inspector.rb +1 -1
- data/lib/mongo/server/description/inspector/description_changed.rb +1 -1
- data/lib/mongo/server/description/inspector/member_discovered.rb +1 -1
- data/lib/mongo/server/description/inspector/primary_elected.rb +1 -1
- data/lib/mongo/server/description/inspector/standalone_discovered.rb +1 -1
- data/lib/mongo/server/monitor.rb +15 -3
- data/lib/mongo/server/monitor/connection.rb +1 -1
- data/lib/mongo/server_selector.rb +1 -1
- data/lib/mongo/server_selector/nearest.rb +1 -1
- data/lib/mongo/server_selector/primary.rb +1 -1
- data/lib/mongo/server_selector/primary_preferred.rb +1 -1
- data/lib/mongo/server_selector/secondary.rb +1 -1
- data/lib/mongo/server_selector/secondary_preferred.rb +1 -1
- data/lib/mongo/server_selector/selectable.rb +7 -2
- data/lib/mongo/session.rb +389 -12
- data/lib/mongo/session/server_session.rb +7 -2
- data/lib/mongo/session/session_pool.rb +1 -1
- data/lib/mongo/socket.rb +1 -1
- data/lib/mongo/socket/ssl.rb +1 -1
- data/lib/mongo/socket/tcp.rb +1 -1
- data/lib/mongo/socket/unix.rb +1 -1
- data/lib/mongo/uri.rb +6 -4
- data/lib/mongo/uri/srv_protocol.rb +1 -1
- data/lib/mongo/version.rb +2 -2
- data/lib/mongo/write_concern.rb +1 -1
- data/lib/mongo/write_concern/acknowledged.rb +1 -1
- data/lib/mongo/write_concern/normalizable.rb +1 -1
- data/lib/mongo/write_concern/unacknowledged.rb +1 -1
- data/mongo.gemspec +4 -1
- data/spec/atlas/atlas_connectivity_spec.rb +54 -0
- data/spec/integration/bulk_insert_spec.rb +78 -0
- data/spec/integration/change_stream_spec.rb +365 -0
- data/spec/integration/command_monitoring_spec.rb +92 -0
- data/spec/lite_spec_helper.rb +63 -0
- data/spec/mongo/address/ipv6_spec.rb +29 -1
- data/spec/mongo/address_spec.rb +34 -0
- data/spec/mongo/auth/scram/conversation_spec.rb +326 -120
- data/spec/mongo/auth/scram/negotiation_spec.rb +574 -0
- data/spec/mongo/auth/scram_spec.rb +107 -38
- data/spec/mongo/auth/stringprep/profiles/sasl_spec.rb +113 -0
- data/spec/mongo/auth/stringprep_spec.rb +188 -0
- data/spec/mongo/auth/user/view_spec.rb +5 -2
- data/spec/mongo/auth/user_spec.rb +1 -1
- data/spec/mongo/bulk_write/result_spec.rb +120 -0
- data/spec/mongo/bulk_write_spec.rb +42 -2
- data/spec/mongo/client_spec.rb +121 -9
- data/spec/mongo/cluster/app_metadata_spec.rb +14 -1
- data/spec/mongo/cluster/topology_spec.rb +1 -23
- data/spec/mongo/collection/view/change_stream_spec.rb +62 -180
- data/spec/mongo/collection_spec.rb +45 -12
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +7 -7
- data/spec/mongo/cursor_spec.rb +2 -2
- data/spec/mongo/database_spec.rb +3 -3
- data/spec/mongo/docs_examples_spec.rb +194 -0
- data/spec/mongo/error/operation_failure_spec.rb +152 -0
- data/spec/mongo/error/parser_spec.rb +127 -0
- data/spec/mongo/grid/fs_bucket_spec.rb +32 -0
- data/spec/mongo/grid/stream/write_spec.rb +40 -1
- data/spec/mongo/monitoring/event/command_failed_spec.rb +30 -0
- data/spec/mongo/monitoring/event/command_started_spec.rb +26 -4
- data/spec/mongo/monitoring/event/command_succeeded_spec.rb +29 -7
- data/spec/mongo/monitoring_spec.rb +28 -3
- data/spec/mongo/protocol/get_more_spec.rb +2 -2
- data/spec/mongo/retryable_spec.rb +252 -34
- data/spec/mongo/retryable_writes_spec.rb +468 -544
- data/spec/mongo/server/connection_spec.rb +5 -5
- data/spec/mongo/server/description_spec.rb +23 -6
- data/spec/mongo/session/server_session_spec.rb +2 -2
- data/spec/mongo/session/session_pool_spec.rb +2 -2
- data/spec/mongo/transactions_examples_spec.rb +227 -0
- data/spec/mongo/transactions_spec.rb +44 -0
- data/spec/spec_helper.rb +135 -49
- data/spec/spec_tests/change_streams_spec.rb +42 -0
- data/spec/{mongo → spec_tests}/command_monitoring_spec.rb +8 -2
- data/spec/{mongo → spec_tests}/connection_string_spec.rb +1 -1
- data/spec/{mongo → spec_tests}/crud_spec.rb +5 -7
- data/spec/{mongo → spec_tests}/dns_seedlist_discovery_spec.rb +1 -1
- data/spec/{mongo → spec_tests}/gridfs_spec.rb +0 -0
- data/spec/{mongo → spec_tests}/max_staleness_spec.rb +0 -0
- data/spec/spec_tests/retryable_writes_spec.rb +78 -0
- data/spec/{mongo → spec_tests}/sdam_monitoring_spec.rb +4 -3
- data/spec/{mongo → spec_tests}/sdam_spec.rb +7 -7
- data/spec/{mongo → spec_tests}/server_selection_rtt_spec.rb +0 -0
- data/spec/{mongo → spec_tests}/server_selection_spec.rb +0 -0
- data/spec/support/authorization.rb +18 -6
- data/spec/support/change_streams.rb +265 -0
- data/spec/support/change_streams/operation.rb +62 -0
- data/spec/support/change_streams_tests/change-streams-errors.yml +53 -0
- data/spec/support/change_streams_tests/change-streams.yml +299 -0
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/command_monitoring/bulkWrite.yml +4 -28
- data/spec/support/command_monitoring/command.yml +19 -0
- data/spec/support/command_monitoring/find.yml +17 -19
- data/spec/support/command_monitoring/insertMany.yml +2 -8
- data/spec/support/command_monitoring/unacknowledgedBulkWrite.yml +34 -0
- data/spec/support/connection_string.rb +1 -1
- data/spec/support/constraints.rb +56 -0
- data/spec/support/crud.rb +9 -4
- data/spec/support/crud/read.rb +24 -3
- data/spec/support/crud/write.rb +7 -2
- data/spec/support/crud_tests/read/count-collation.yml +12 -2
- data/spec/support/crud_tests/read/count.yml +43 -5
- data/spec/support/gridfs.rb +1 -1
- data/spec/support/primary_socket.rb +21 -0
- data/spec/support/retryable_writes_tests/bulkWrite-serverErrors.yml +90 -0
- data/spec/support/retryable_writes_tests/bulkWrite.yml +99 -1
- data/spec/support/retryable_writes_tests/deleteOne-serverErrors.yml +50 -0
- data/spec/support/retryable_writes_tests/deleteOne.yml +10 -1
- data/spec/support/retryable_writes_tests/findOneAndDelete-serverErrors.yml +50 -0
- data/spec/support/retryable_writes_tests/findOneAndDelete.yml +39 -30
- data/spec/support/retryable_writes_tests/findOneAndReplace-serverErrors.yml +54 -0
- data/spec/support/retryable_writes_tests/findOneAndReplace.yml +9 -0
- data/spec/support/retryable_writes_tests/findOneAndUpdate-serverErrors.yml +54 -0
- data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +9 -0
- data/spec/support/retryable_writes_tests/insertMany-serverErrors.yml +59 -0
- data/spec/support/retryable_writes_tests/insertMany.yml +11 -6
- data/spec/support/retryable_writes_tests/insertOne-serverErrors.yml +471 -0
- data/spec/support/retryable_writes_tests/insertOne.yml +9 -0
- data/spec/support/retryable_writes_tests/replaceOne-serverErrors.yml +58 -0
- data/spec/support/retryable_writes_tests/replaceOne.yml +9 -0
- data/spec/support/retryable_writes_tests/updateOne-serverErrors.yml +58 -0
- data/spec/support/retryable_writes_tests/updateOne.yml +71 -53
- data/spec/support/sdam/rs/normalize_case_me.yml +100 -0
- data/spec/support/sdam/sharded/compatible.yml +38 -0
- data/spec/support/sdam/sharded/mongos_disconnect.yml +9 -3
- data/spec/support/sdam/sharded/multiple_mongoses.yml +6 -2
- data/spec/support/sdam/sharded/non_mongos_removed.yml +6 -2
- data/spec/support/sdam/sharded/too_new.yml +36 -0
- data/spec/support/sdam/sharded/too_old.yml +36 -0
- data/spec/support/sdam/single/compatible.yml +26 -0
- data/spec/support/sdam/single/direct_connection_external_ip.yml +3 -1
- data/spec/support/sdam/single/direct_connection_mongos.yml +3 -1
- data/spec/support/sdam/single/direct_connection_rsarbiter.yml +3 -1
- data/spec/support/sdam/single/direct_connection_rsprimary.yml +3 -1
- data/spec/support/sdam/single/direct_connection_rssecondary.yml +3 -1
- data/spec/support/sdam/single/direct_connection_slave.yml +3 -1
- data/spec/support/sdam/single/direct_connection_standalone.yml +3 -1
- data/spec/support/sdam/single/not_ok_response.yml +6 -2
- data/spec/support/sdam/single/standalone_removed.yml +3 -1
- data/spec/support/sdam/single/too_new.yml +26 -0
- data/spec/support/sdam/single/too_old.yml +24 -0
- data/spec/support/shared/session.rb +107 -0
- data/spec/support/transactions.rb +391 -0
- data/spec/support/transactions/operation.rb +373 -0
- data/spec/support/transactions_tests/abort.yml +403 -0
- data/spec/support/transactions_tests/bulk.yml +267 -0
- data/spec/support/transactions_tests/causal-consistency.yml +173 -0
- data/spec/support/transactions_tests/commit.yml +593 -0
- data/spec/support/transactions_tests/delete.yml +184 -0
- data/spec/support/transactions_tests/error-labels.yml +948 -0
- data/spec/support/transactions_tests/errors.yml +125 -0
- data/spec/support/transactions_tests/findOneAndDelete.yml +126 -0
- data/spec/support/transactions_tests/findOneAndReplace.yml +140 -0
- data/spec/support/transactions_tests/findOneAndUpdate.yml +228 -0
- data/spec/support/transactions_tests/insert.yml +264 -0
- data/spec/support/transactions_tests/isolation.yml +125 -0
- data/spec/support/transactions_tests/read-pref.yml +340 -0
- data/spec/support/transactions_tests/reads.yml +298 -0
- data/spec/support/transactions_tests/retryable-abort.yml +1292 -0
- data/spec/support/transactions_tests/retryable-commit.yml +1332 -0
- data/spec/support/transactions_tests/retryable-writes.yml +208 -0
- data/spec/support/transactions_tests/run-command.yml +189 -0
- data/spec/support/transactions_tests/transaction-options.yml +877 -0
- data/spec/support/transactions_tests/update.yml +246 -0
- data/spec/support/transactions_tests/write-concern.yml +236 -0
- metadata +494 -359
- metadata.gz.sig +0 -0
- data/lib/csasl/csasl.bundle +0 -0
@@ -1,813 +1,737 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'Retryable
|
3
|
+
describe 'Retryable writes integration tests' do
|
4
|
+
include PrimarySocket
|
4
5
|
|
5
|
-
|
6
|
+
after do
|
7
|
+
authorized_collection.delete_many
|
8
|
+
end
|
6
9
|
|
7
|
-
|
10
|
+
shared_examples_for 'an operation that is retried' do
|
8
11
|
|
9
|
-
context
|
12
|
+
context 'when the operation fails on the first attempt' do
|
10
13
|
|
11
|
-
|
14
|
+
before do
|
15
|
+
# Note that for writes, server.connectable? is called, refreshing the socket
|
16
|
+
allow(primary_server).to receive(:connectable?).and_return(true)
|
17
|
+
expect(primary_socket).to receive(:write).and_raise(error)
|
18
|
+
end
|
12
19
|
|
13
|
-
|
20
|
+
context 'when the error is retryable' do
|
14
21
|
|
15
|
-
|
16
|
-
|
17
|
-
|
22
|
+
before do
|
23
|
+
expect(Mongo::Logger.logger).to receive(:warn).once.and_call_original
|
24
|
+
expect(client.cluster).to receive(:scan!)
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when the error is a SocketError' do
|
18
28
|
|
19
|
-
let(:
|
20
|
-
|
29
|
+
let(:error) do
|
30
|
+
Mongo::Error::SocketError
|
21
31
|
end
|
22
32
|
|
23
|
-
|
24
|
-
|
33
|
+
it 'retries writes' do
|
34
|
+
operation
|
35
|
+
expect(expectation).to eq(successful_retry_value)
|
25
36
|
end
|
37
|
+
end
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
context 'when the error is a SocketTimeoutError' do
|
40
|
+
|
41
|
+
let(:error) do
|
42
|
+
Mongo::Error::SocketTimeoutError
|
30
43
|
end
|
31
44
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
begin; test.run(collection); rescue => e; error = e; end
|
36
|
-
error
|
37
|
-
else
|
38
|
-
test.run(collection)
|
39
|
-
end
|
45
|
+
it 'retries writes' do
|
46
|
+
operation
|
47
|
+
expect(expectation).to eq(successful_retry_value)
|
40
48
|
end
|
49
|
+
end
|
41
50
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
51
|
+
context 'when the error is a retryable OperationFailure' do
|
52
|
+
|
53
|
+
let(:error) do
|
54
|
+
Mongo::Error::OperationFailure.new('not master')
|
46
55
|
end
|
47
56
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
expect(results).to be_a(Mongo::Error)
|
52
|
-
end
|
53
|
-
else
|
54
|
-
it 'returns the correct result', if: sessions_enabled? && replica_set? do
|
55
|
-
skip 'Test cannot be run on this server version' unless spec.server_version_satisfied?(client)
|
56
|
-
expect(results).to match_operation_result(test)
|
57
|
-
end
|
57
|
+
it 'retries writes' do
|
58
|
+
operation
|
59
|
+
expect(expectation).to eq(successful_retry_value)
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
61
|
-
end
|
62
|
-
end
|
63
63
|
|
64
|
-
|
64
|
+
context 'when the error is not retryable' do
|
65
65
|
|
66
|
-
|
67
|
-
primary = client.cluster.next_primary
|
68
|
-
end
|
66
|
+
context 'when the error is a non-retryable OperationFailure' do
|
69
67
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
primary.pool.checkin(connection)
|
74
|
-
connection
|
75
|
-
end
|
68
|
+
let(:error) do
|
69
|
+
Mongo::Error::OperationFailure.new('other error')
|
70
|
+
end
|
76
71
|
|
77
|
-
|
78
|
-
|
72
|
+
it 'does not retry writes' do
|
73
|
+
expect {
|
74
|
+
operation
|
75
|
+
}.to raise_error(error)
|
76
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
79
80
|
end
|
80
81
|
|
81
|
-
|
82
|
-
authorized_collection.delete_many
|
83
|
-
end
|
82
|
+
context 'when the operation fails on the first attempt and again on the second attempt' do
|
84
83
|
|
85
|
-
|
84
|
+
before do
|
85
|
+
# Note that for writes, server.connectable? is called, refreshing the socket
|
86
|
+
allow(primary_server).to receive(:connectable?).and_return(true)
|
87
|
+
allow(primary_socket).to receive(:write).and_raise(error)
|
88
|
+
end
|
86
89
|
|
87
|
-
context 'when the
|
90
|
+
context 'when the selected server does not support retryable writes' do
|
88
91
|
|
89
92
|
before do
|
90
|
-
|
91
|
-
allow(
|
93
|
+
legacy_primary = double('legacy primary', :'retry_writes?' => false)
|
94
|
+
allow(client.cluster).to receive(:next_primary).and_return(primary_server, legacy_primary)
|
92
95
|
expect(primary_socket).to receive(:write).and_raise(error)
|
93
96
|
end
|
94
97
|
|
95
|
-
context 'when the error is
|
98
|
+
context 'when the error is a SocketError' do
|
96
99
|
|
97
|
-
|
98
|
-
|
99
|
-
expect(client.cluster).to receive(:scan!)
|
100
|
+
let(:error) do
|
101
|
+
Mongo::Error::SocketError
|
100
102
|
end
|
101
103
|
|
102
|
-
|
103
|
-
|
104
|
-
let(:error) do
|
105
|
-
Mongo::Error::SocketError
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'retries writes' do
|
104
|
+
it 'does not retry writes and raises the original error' do
|
105
|
+
expect {
|
109
106
|
operation
|
110
|
-
|
111
|
-
|
107
|
+
}.to raise_error(error)
|
108
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
112
109
|
end
|
110
|
+
end
|
113
111
|
|
114
|
-
|
115
|
-
|
116
|
-
let(:error) do
|
117
|
-
Mongo::Error::SocketTimeoutError
|
118
|
-
end
|
112
|
+
context 'when the error is a SocketTimeoutError' do
|
119
113
|
|
120
|
-
|
121
|
-
|
122
|
-
expect(expectation).to eq(successful_retry_value)
|
123
|
-
end
|
114
|
+
let(:error) do
|
115
|
+
Mongo::Error::SocketTimeoutError
|
124
116
|
end
|
125
117
|
|
126
|
-
|
127
|
-
|
128
|
-
let(:error) do
|
129
|
-
Mongo::Error::OperationFailure.new('not master')
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'retries writes' do
|
118
|
+
it 'does not retry writes and raises the original error' do
|
119
|
+
expect {
|
133
120
|
operation
|
134
|
-
|
135
|
-
|
121
|
+
}.to raise_error(error)
|
122
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
136
123
|
end
|
137
124
|
end
|
138
125
|
|
139
|
-
context 'when the error is
|
140
|
-
|
141
|
-
context 'when the error is a non-retryable OperationFailure' do
|
126
|
+
context 'when the error is a retryable OperationFailure' do
|
142
127
|
|
143
|
-
|
144
|
-
|
145
|
-
|
128
|
+
let(:error) do
|
129
|
+
Mongo::Error::OperationFailure.new('not master')
|
130
|
+
end
|
146
131
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
132
|
+
it 'does not retry writes and raises the original error' do
|
133
|
+
expect {
|
134
|
+
operation
|
135
|
+
}.to raise_error(error)
|
136
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
153
137
|
end
|
154
138
|
end
|
155
139
|
end
|
156
140
|
|
157
|
-
|
141
|
+
[Mongo::Error::SocketError,
|
142
|
+
Mongo::Error::SocketTimeoutError,
|
143
|
+
Mongo::Error::OperationFailure.new('not master')].each do |retryable_error|
|
158
144
|
|
159
|
-
|
160
|
-
# Note that for writes, server.connectable? is called, refreshing the socket
|
161
|
-
allow(primary).to receive(:connectable?).and_return(true)
|
162
|
-
allow(primary_socket).to receive(:write).and_raise(error)
|
163
|
-
end
|
145
|
+
context "when the first error is a #{retryable_error}" do
|
164
146
|
|
165
|
-
|
147
|
+
let(:error) do
|
148
|
+
retryable_error
|
149
|
+
end
|
166
150
|
|
167
151
|
before do
|
168
|
-
|
169
|
-
|
170
|
-
|
152
|
+
bad_socket = primary_connection.address.socket(primary_connection.socket_timeout,
|
153
|
+
primary_connection.send(:ssl_options))
|
154
|
+
good_socket = primary_connection.address.socket(primary_connection.socket_timeout,
|
155
|
+
primary_connection.send(:ssl_options))
|
156
|
+
allow(bad_socket).to receive(:write).and_raise(second_error)
|
157
|
+
allow(primary_connection.address).to receive(:socket).and_return(bad_socket, good_socket)
|
171
158
|
end
|
172
159
|
|
173
|
-
context 'when the error is a SocketError' do
|
160
|
+
context 'when the second error is a SocketError' do
|
174
161
|
|
175
|
-
let(:
|
162
|
+
let(:second_error) do
|
176
163
|
Mongo::Error::SocketError
|
177
164
|
end
|
178
165
|
|
179
|
-
|
166
|
+
before do
|
167
|
+
expect(client.cluster).to receive(:scan!).twice
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'does not retry writes and raises the second error' do
|
180
171
|
expect {
|
181
172
|
operation
|
182
|
-
}.to raise_error(
|
173
|
+
}.to raise_error(second_error)
|
183
174
|
expect(expectation).to eq(unsuccessful_retry_value)
|
184
175
|
end
|
185
176
|
end
|
186
177
|
|
187
|
-
context 'when the error is a SocketTimeoutError' do
|
178
|
+
context 'when the second error is a SocketTimeoutError' do
|
188
179
|
|
189
|
-
|
180
|
+
before do
|
181
|
+
expect(client.cluster).to receive(:scan!).twice
|
182
|
+
end
|
183
|
+
|
184
|
+
let(:second_error) do
|
190
185
|
Mongo::Error::SocketTimeoutError
|
191
186
|
end
|
192
187
|
|
193
|
-
it 'does not retry writes and raises the
|
188
|
+
it 'does not retry writes and raises the second error' do
|
194
189
|
expect {
|
195
190
|
operation
|
196
|
-
}.to raise_error(
|
191
|
+
}.to raise_error(second_error)
|
197
192
|
expect(expectation).to eq(unsuccessful_retry_value)
|
198
193
|
end
|
199
194
|
end
|
200
195
|
|
201
|
-
context 'when the error is a retryable OperationFailure' do
|
196
|
+
context 'when the second error is a retryable OperationFailure' do
|
202
197
|
|
203
|
-
|
198
|
+
before do
|
199
|
+
expect(client.cluster).to receive(:scan!).twice
|
200
|
+
end
|
201
|
+
|
202
|
+
let(:second_error) do
|
204
203
|
Mongo::Error::OperationFailure.new('not master')
|
205
204
|
end
|
206
205
|
|
207
|
-
it 'does not retry writes and raises the
|
206
|
+
it 'does not retry writes and raises the second error' do
|
208
207
|
expect {
|
209
208
|
operation
|
210
|
-
}.to raise_error(
|
209
|
+
}.to raise_error(second_error)
|
211
210
|
expect(expectation).to eq(unsuccessful_retry_value)
|
212
211
|
end
|
213
212
|
end
|
214
|
-
end
|
215
|
-
|
216
|
-
[Mongo::Error::SocketError,
|
217
|
-
Mongo::Error::SocketTimeoutError,
|
218
|
-
Mongo::Error::OperationFailure.new('not master')].each do |retryable_error|
|
219
213
|
|
220
|
-
context
|
221
|
-
|
222
|
-
let(:error) do
|
223
|
-
retryable_error
|
224
|
-
end
|
214
|
+
context 'when the second error is a non-retryable OperationFailure' do
|
225
215
|
|
226
216
|
before do
|
227
|
-
|
228
|
-
primary_connection.send(:ssl_options))
|
229
|
-
good_socket = primary_connection.address.socket(primary_connection.socket_timeout,
|
230
|
-
primary_connection.send(:ssl_options))
|
231
|
-
allow(bad_socket).to receive(:write).and_raise(second_error)
|
232
|
-
allow(primary_connection.address).to receive(:socket).and_return(bad_socket, good_socket)
|
217
|
+
expect(client.cluster).to receive(:scan!).once
|
233
218
|
end
|
234
219
|
|
235
|
-
|
236
|
-
|
237
|
-
let(:second_error) do
|
238
|
-
Mongo::Error::SocketError
|
239
|
-
end
|
240
|
-
|
241
|
-
before do
|
242
|
-
expect(client.cluster).to receive(:scan!).twice
|
243
|
-
end
|
244
|
-
|
245
|
-
it 'does not retry writes and raises the second error' do
|
246
|
-
expect {
|
247
|
-
operation
|
248
|
-
}.to raise_error(second_error)
|
249
|
-
expect(expectation).to eq(unsuccessful_retry_value)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
context 'when the second error is a SocketTimeoutError' do
|
254
|
-
|
255
|
-
before do
|
256
|
-
expect(client.cluster).to receive(:scan!).twice
|
257
|
-
end
|
258
|
-
|
259
|
-
let(:second_error) do
|
260
|
-
Mongo::Error::SocketTimeoutError
|
261
|
-
end
|
262
|
-
|
263
|
-
it 'does not retry writes and raises the second error' do
|
264
|
-
expect {
|
265
|
-
operation
|
266
|
-
}.to raise_error(second_error)
|
267
|
-
expect(expectation).to eq(unsuccessful_retry_value)
|
268
|
-
end
|
220
|
+
let(:second_error) do
|
221
|
+
Mongo::Error::OperationFailure.new('other error')
|
269
222
|
end
|
270
223
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
let(:second_error) do
|
278
|
-
Mongo::Error::OperationFailure.new('not master')
|
279
|
-
end
|
280
|
-
|
281
|
-
it 'does not retry writes and raises the second error' do
|
282
|
-
expect {
|
283
|
-
operation
|
284
|
-
}.to raise_error(second_error)
|
285
|
-
expect(expectation).to eq(unsuccessful_retry_value)
|
286
|
-
end
|
224
|
+
it 'does not retry writes and raises the first error' do
|
225
|
+
expect {
|
226
|
+
operation
|
227
|
+
}.to raise_error(error)
|
228
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
287
229
|
end
|
230
|
+
end
|
288
231
|
|
289
|
-
|
290
|
-
|
291
|
-
before do
|
292
|
-
expect(client.cluster).to receive(:scan!).once
|
293
|
-
end
|
294
|
-
|
295
|
-
let(:second_error) do
|
296
|
-
Mongo::Error::OperationFailure.new('other error')
|
297
|
-
end
|
232
|
+
context 'when the second error is a another error' do
|
298
233
|
|
299
|
-
|
300
|
-
|
301
|
-
operation
|
302
|
-
}.to raise_error(error)
|
303
|
-
expect(expectation).to eq(unsuccessful_retry_value)
|
304
|
-
end
|
234
|
+
let(:second_error) do
|
235
|
+
StandardError
|
305
236
|
end
|
306
237
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
it 'does not retry writes and raises the first error' do
|
314
|
-
expect {
|
315
|
-
operation
|
316
|
-
}.to raise_error(error)
|
317
|
-
expect(expectation).to eq(unsuccessful_retry_value)
|
318
|
-
end
|
238
|
+
it 'does not retry writes and raises the first error' do
|
239
|
+
expect {
|
240
|
+
operation
|
241
|
+
}.to raise_error(error)
|
242
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
319
243
|
end
|
320
244
|
end
|
321
245
|
end
|
322
246
|
end
|
323
247
|
end
|
248
|
+
end
|
324
249
|
|
325
|
-
|
326
|
-
|
327
|
-
before do
|
328
|
-
# Note that for writes, server.connectable? is called, refreshing the socket
|
329
|
-
allow(primary).to receive(:connectable?).and_return(true)
|
330
|
-
expect(primary_socket).to receive(:write).and_raise(Mongo::Error::SocketError)
|
331
|
-
expect(client.cluster).not_to receive(:scan!)
|
332
|
-
end
|
250
|
+
shared_examples_for 'an operation that is not retried' do
|
333
251
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
end
|
252
|
+
before do
|
253
|
+
# Note that for writes, server.connectable? is called, refreshing the socket
|
254
|
+
allow(primary_server).to receive(:connectable?).and_return(true)
|
255
|
+
expect(primary_socket).to receive(:write).and_raise(Mongo::Error::SocketError)
|
256
|
+
expect(client.cluster).not_to receive(:scan!)
|
340
257
|
end
|
341
258
|
|
342
|
-
|
259
|
+
it 'does not retry writes' do
|
260
|
+
expect {
|
261
|
+
operation
|
262
|
+
}.to raise_error(Mongo::Error::SocketError)
|
263
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
264
|
+
end
|
265
|
+
end
|
343
266
|
|
344
|
-
|
345
|
-
authorized_client_with_retry_writes
|
346
|
-
end
|
267
|
+
shared_examples_for 'an operation that does not support retryable writes' do
|
347
268
|
|
348
|
-
|
349
|
-
|
350
|
-
|
269
|
+
let!(:client) do
|
270
|
+
authorized_client_with_retry_writes
|
271
|
+
end
|
351
272
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
expect(primary_socket).to receive(:write).and_raise(Mongo::Error::SocketError)
|
356
|
-
expect(client.cluster).not_to receive(:scan!)
|
357
|
-
end
|
273
|
+
let!(:collection) do
|
274
|
+
client[TEST_COLL, write: WRITE_CONCERN]
|
275
|
+
end
|
358
276
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
end
|
277
|
+
before do
|
278
|
+
# Note that for writes, server.connectable? is called, refreshing the socket
|
279
|
+
allow(primary_server).to receive(:connectable?).and_return(true)
|
280
|
+
expect(primary_socket).to receive(:write).and_raise(Mongo::Error::SocketError)
|
281
|
+
expect(client.cluster).not_to receive(:scan!)
|
365
282
|
end
|
366
283
|
|
367
|
-
|
284
|
+
it 'does not retry writes' do
|
285
|
+
expect {
|
286
|
+
operation
|
287
|
+
}.to raise_error(Mongo::Error::SocketError)
|
288
|
+
expect(expectation).to eq(unsuccessful_retry_value)
|
289
|
+
end
|
290
|
+
end
|
368
291
|
|
369
|
-
|
292
|
+
shared_examples_for 'supported retryable writes' do
|
370
293
|
|
371
|
-
|
372
|
-
authorized_client_with_retry_writes
|
373
|
-
end
|
294
|
+
context 'when the client has retry_writes set to true' do
|
374
295
|
|
375
|
-
|
296
|
+
let!(:client) do
|
297
|
+
authorized_client_with_retry_writes
|
298
|
+
end
|
376
299
|
|
377
|
-
|
378
|
-
client[TEST_COLL, write: WRITE_CONCERN]
|
379
|
-
end
|
300
|
+
context 'when the collection has write concern acknowledged' do
|
380
301
|
|
381
|
-
|
302
|
+
let!(:collection) do
|
303
|
+
client[TEST_COLL, write: WRITE_CONCERN]
|
304
|
+
end
|
382
305
|
|
383
|
-
|
384
|
-
allow(primary).to receive(:retry_writes?).and_return(true)
|
385
|
-
end
|
306
|
+
context 'when the server supports retryable writes' do
|
386
307
|
|
387
|
-
|
388
|
-
|
389
|
-
elsif sessions_enabled?
|
390
|
-
it_behaves_like 'an operation that is retried'
|
391
|
-
end
|
308
|
+
before do
|
309
|
+
allow(primary_server).to receive(:retry_writes?).and_return(true)
|
392
310
|
end
|
393
311
|
|
394
|
-
|
395
|
-
|
396
|
-
before do
|
397
|
-
allow(primary).to receive(:retry_writes?).and_return(false)
|
398
|
-
end
|
399
|
-
|
312
|
+
if standalone? && sessions_enabled?
|
400
313
|
it_behaves_like 'an operation that is not retried'
|
314
|
+
elsif sessions_enabled?
|
315
|
+
it_behaves_like 'an operation that is retried'
|
401
316
|
end
|
402
317
|
end
|
403
318
|
|
404
|
-
context 'when the
|
319
|
+
context 'when the server does not support retryable writes' do
|
405
320
|
|
406
|
-
|
407
|
-
|
321
|
+
before do
|
322
|
+
allow(primary_server).to receive(:retry_writes?).and_return(false)
|
408
323
|
end
|
409
324
|
|
410
325
|
it_behaves_like 'an operation that is not retried'
|
411
326
|
end
|
327
|
+
end
|
412
328
|
|
413
|
-
|
329
|
+
context 'when the collection has write concern unacknowledged' do
|
414
330
|
|
415
|
-
|
416
|
-
|
417
|
-
|
331
|
+
let!(:collection) do
|
332
|
+
client[TEST_COLL, write: { w: 0 }]
|
333
|
+
end
|
418
334
|
|
419
|
-
|
335
|
+
it_behaves_like 'an operation that is not retried'
|
336
|
+
end
|
420
337
|
|
421
|
-
|
422
|
-
allow(primary).to receive(:retry_writes?).and_return(true)
|
423
|
-
end
|
338
|
+
context 'when the collection has write concern not set' do
|
424
339
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
it_behaves_like 'an operation that is retried'
|
429
|
-
end
|
430
|
-
end
|
340
|
+
let!(:collection) do
|
341
|
+
client[TEST_COLL]
|
342
|
+
end
|
431
343
|
|
432
|
-
|
344
|
+
context 'when the server supports retryable writes' do
|
433
345
|
|
434
|
-
|
435
|
-
|
436
|
-
|
346
|
+
before do
|
347
|
+
allow(primary_server).to receive(:retry_writes?).and_return(true)
|
348
|
+
end
|
437
349
|
|
350
|
+
if standalone? && sessions_enabled?
|
438
351
|
it_behaves_like 'an operation that is not retried'
|
352
|
+
elsif sessions_enabled?
|
353
|
+
it_behaves_like 'an operation that is retried'
|
439
354
|
end
|
440
355
|
end
|
441
|
-
end
|
442
|
-
|
443
|
-
context 'when the client has retry_writes set to false' do
|
444
|
-
|
445
|
-
let!(:client) do
|
446
|
-
authorized_client.with(retry_writes: false)
|
447
|
-
end
|
448
|
-
|
449
|
-
after do
|
450
|
-
client.close
|
451
|
-
end
|
452
356
|
|
453
|
-
context 'when the
|
357
|
+
context 'when the server does not support retryable writes' do
|
454
358
|
|
455
|
-
|
456
|
-
|
359
|
+
before do
|
360
|
+
allow(primary_server).to receive(:retry_writes?).and_return(false)
|
457
361
|
end
|
458
362
|
|
459
363
|
it_behaves_like 'an operation that is not retried'
|
460
364
|
end
|
365
|
+
end
|
366
|
+
end
|
461
367
|
|
462
|
-
|
368
|
+
context 'when the client has retry_writes set to false' do
|
463
369
|
|
464
|
-
|
465
|
-
|
466
|
-
|
370
|
+
let!(:client) do
|
371
|
+
authorized_client.with(retry_writes: false)
|
372
|
+
end
|
467
373
|
|
468
|
-
|
374
|
+
after do
|
375
|
+
client.close
|
376
|
+
end
|
377
|
+
|
378
|
+
context 'when the collection has write concern acknowledged' do
|
379
|
+
|
380
|
+
let!(:collection) do
|
381
|
+
client[TEST_COLL, write: WRITE_CONCERN]
|
469
382
|
end
|
470
383
|
|
471
|
-
|
384
|
+
it_behaves_like 'an operation that is not retried'
|
385
|
+
end
|
472
386
|
|
473
|
-
|
474
|
-
client[TEST_COLL]
|
475
|
-
end
|
387
|
+
context 'when the collection has write concern unacknowledged' do
|
476
388
|
|
477
|
-
|
389
|
+
let!(:collection) do
|
390
|
+
client[TEST_COLL, write: { w: 0 }]
|
478
391
|
end
|
392
|
+
|
393
|
+
it_behaves_like 'an operation that is not retried'
|
479
394
|
end
|
480
395
|
|
481
|
-
context 'when the
|
396
|
+
context 'when the collection has write concern not set' do
|
482
397
|
|
483
|
-
let!(:
|
484
|
-
|
398
|
+
let!(:collection) do
|
399
|
+
client[TEST_COLL]
|
485
400
|
end
|
486
401
|
|
487
|
-
|
402
|
+
it_behaves_like 'an operation that is not retried'
|
403
|
+
end
|
404
|
+
end
|
488
405
|
|
489
|
-
|
490
|
-
client[TEST_COLL, write: WRITE_CONCERN]
|
491
|
-
end
|
406
|
+
context 'when the client has retry_writes not set' do
|
492
407
|
|
493
|
-
|
408
|
+
let!(:client) do
|
409
|
+
authorized_client
|
410
|
+
end
|
411
|
+
|
412
|
+
context 'when the collection has write concern acknowledged' do
|
413
|
+
|
414
|
+
let!(:collection) do
|
415
|
+
client[TEST_COLL, write: WRITE_CONCERN]
|
494
416
|
end
|
495
417
|
|
496
|
-
|
418
|
+
it_behaves_like 'an operation that is not retried'
|
419
|
+
end
|
497
420
|
|
498
|
-
|
499
|
-
client[TEST_COLL, write: { w: 0 }]
|
500
|
-
end
|
421
|
+
context 'when the collection has write concern unacknowledged' do
|
501
422
|
|
502
|
-
|
423
|
+
let!(:collection) do
|
424
|
+
client[TEST_COLL, write: { w: 0 }]
|
503
425
|
end
|
504
426
|
|
505
|
-
|
427
|
+
it_behaves_like 'an operation that is not retried'
|
428
|
+
end
|
506
429
|
|
507
|
-
|
508
|
-
client[TEST_COLL]
|
509
|
-
end
|
430
|
+
context 'when the collection has write concern not set' do
|
510
431
|
|
511
|
-
|
432
|
+
let!(:collection) do
|
433
|
+
client[TEST_COLL]
|
512
434
|
end
|
435
|
+
|
436
|
+
it_behaves_like 'an operation that is not retried'
|
513
437
|
end
|
514
438
|
end
|
439
|
+
end
|
515
440
|
|
516
|
-
|
517
|
-
|
518
|
-
let(:operation) do
|
519
|
-
collection.insert_one(a:1)
|
520
|
-
end
|
441
|
+
context 'when the operation is insert_one' do
|
521
442
|
|
522
|
-
|
523
|
-
|
524
|
-
|
443
|
+
let(:operation) do
|
444
|
+
collection.insert_one(a:1)
|
445
|
+
end
|
525
446
|
|
526
|
-
|
527
|
-
|
528
|
-
|
447
|
+
let(:expectation) do
|
448
|
+
collection.find(a: 1).count
|
449
|
+
end
|
529
450
|
|
530
|
-
|
531
|
-
|
532
|
-
|
451
|
+
let(:successful_retry_value) do
|
452
|
+
1
|
453
|
+
end
|
533
454
|
|
534
|
-
|
455
|
+
let(:unsuccessful_retry_value) do
|
456
|
+
0
|
535
457
|
end
|
536
458
|
|
537
|
-
|
459
|
+
it_behaves_like 'supported retryable writes'
|
460
|
+
end
|
538
461
|
|
539
|
-
|
540
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
541
|
-
authorized_collection.insert_one(a:0)
|
542
|
-
end
|
462
|
+
context 'when the operation is update_one' do
|
543
463
|
|
544
|
-
|
545
|
-
|
546
|
-
|
464
|
+
before do
|
465
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
466
|
+
authorized_collection.insert_one(a:0)
|
467
|
+
end
|
547
468
|
|
548
|
-
|
549
|
-
|
550
|
-
|
469
|
+
let(:operation) do
|
470
|
+
collection.update_one({ a: 0 }, { '$set' => { a: 1 } })
|
471
|
+
end
|
551
472
|
|
552
|
-
|
553
|
-
|
554
|
-
|
473
|
+
let(:expectation) do
|
474
|
+
collection.find(a: 1).count
|
475
|
+
end
|
555
476
|
|
556
|
-
|
557
|
-
|
558
|
-
|
477
|
+
let(:successful_retry_value) do
|
478
|
+
1
|
479
|
+
end
|
559
480
|
|
560
|
-
|
481
|
+
let(:unsuccessful_retry_value) do
|
482
|
+
0
|
561
483
|
end
|
562
484
|
|
563
|
-
|
485
|
+
it_behaves_like 'supported retryable writes'
|
486
|
+
end
|
564
487
|
|
565
|
-
|
566
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
567
|
-
authorized_collection.insert_one(a:0)
|
568
|
-
end
|
488
|
+
context 'when the operation is replace_one' do
|
569
489
|
|
570
|
-
|
571
|
-
|
572
|
-
|
490
|
+
before do
|
491
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
492
|
+
authorized_collection.insert_one(a:0)
|
493
|
+
end
|
573
494
|
|
574
|
-
|
575
|
-
|
576
|
-
|
495
|
+
let(:operation) do
|
496
|
+
collection.replace_one({ a: 0 }, { a: 1 })
|
497
|
+
end
|
577
498
|
|
578
|
-
|
579
|
-
|
580
|
-
|
499
|
+
let(:expectation) do
|
500
|
+
collection.find(a: 1).count
|
501
|
+
end
|
581
502
|
|
582
|
-
|
583
|
-
|
584
|
-
|
503
|
+
let(:successful_retry_value) do
|
504
|
+
1
|
505
|
+
end
|
585
506
|
|
586
|
-
|
507
|
+
let(:unsuccessful_retry_value) do
|
508
|
+
0
|
587
509
|
end
|
588
510
|
|
589
|
-
|
511
|
+
it_behaves_like 'supported retryable writes'
|
512
|
+
end
|
590
513
|
|
591
|
-
|
592
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
593
|
-
authorized_collection.insert_one(a:1)
|
594
|
-
end
|
514
|
+
context 'when the operation is delete_one' do
|
595
515
|
|
596
|
-
|
597
|
-
|
598
|
-
|
516
|
+
before do
|
517
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
518
|
+
authorized_collection.insert_one(a:1)
|
519
|
+
end
|
599
520
|
|
600
|
-
|
601
|
-
|
602
|
-
|
521
|
+
let(:operation) do
|
522
|
+
collection.delete_one(a:1)
|
523
|
+
end
|
603
524
|
|
604
|
-
|
605
|
-
|
606
|
-
|
525
|
+
let(:expectation) do
|
526
|
+
collection.find(a: 1).count
|
527
|
+
end
|
607
528
|
|
608
|
-
|
609
|
-
|
610
|
-
|
529
|
+
let(:successful_retry_value) do
|
530
|
+
0
|
531
|
+
end
|
611
532
|
|
612
|
-
|
533
|
+
let(:unsuccessful_retry_value) do
|
534
|
+
1
|
613
535
|
end
|
614
536
|
|
615
|
-
|
537
|
+
it_behaves_like 'supported retryable writes'
|
538
|
+
end
|
616
539
|
|
617
|
-
|
618
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
619
|
-
authorized_collection.insert_one(a:0)
|
620
|
-
end
|
540
|
+
context 'when the operation is find_one_and_update' do
|
621
541
|
|
622
|
-
|
623
|
-
|
624
|
-
|
542
|
+
before do
|
543
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
544
|
+
authorized_collection.insert_one(a:0)
|
545
|
+
end
|
625
546
|
|
626
|
-
|
627
|
-
|
628
|
-
|
547
|
+
let(:operation) do
|
548
|
+
collection.find_one_and_update({ a: 0 }, { '$set' => { a: 1 } })
|
549
|
+
end
|
629
550
|
|
630
|
-
|
631
|
-
|
632
|
-
|
551
|
+
let(:expectation) do
|
552
|
+
collection.find(a: 1).count
|
553
|
+
end
|
633
554
|
|
634
|
-
|
635
|
-
|
636
|
-
|
555
|
+
let(:successful_retry_value) do
|
556
|
+
1
|
557
|
+
end
|
637
558
|
|
638
|
-
|
559
|
+
let(:unsuccessful_retry_value) do
|
560
|
+
0
|
639
561
|
end
|
640
562
|
|
641
|
-
|
563
|
+
it_behaves_like 'supported retryable writes'
|
564
|
+
end
|
642
565
|
|
643
|
-
|
644
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
645
|
-
authorized_collection.insert_one(a:0)
|
646
|
-
end
|
566
|
+
context 'when the operation is find_one_and_replace' do
|
647
567
|
|
648
|
-
|
649
|
-
|
650
|
-
|
568
|
+
before do
|
569
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
570
|
+
authorized_collection.insert_one(a:0)
|
571
|
+
end
|
651
572
|
|
652
|
-
|
653
|
-
|
654
|
-
|
573
|
+
let(:operation) do
|
574
|
+
collection.find_one_and_replace({ a: 0 }, { a: 3 })
|
575
|
+
end
|
655
576
|
|
656
|
-
|
657
|
-
|
658
|
-
|
577
|
+
let(:expectation) do
|
578
|
+
collection.find(a: 3).count
|
579
|
+
end
|
659
580
|
|
660
|
-
|
661
|
-
|
662
|
-
|
581
|
+
let(:successful_retry_value) do
|
582
|
+
1
|
583
|
+
end
|
663
584
|
|
664
|
-
|
585
|
+
let(:unsuccessful_retry_value) do
|
586
|
+
0
|
665
587
|
end
|
666
588
|
|
667
|
-
|
589
|
+
it_behaves_like 'supported retryable writes'
|
590
|
+
end
|
668
591
|
|
669
|
-
|
670
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
671
|
-
authorized_collection.insert_one(a:1)
|
672
|
-
end
|
592
|
+
context 'when the operation is find_one_and_delete' do
|
673
593
|
|
674
|
-
|
675
|
-
|
676
|
-
|
594
|
+
before do
|
595
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
596
|
+
authorized_collection.insert_one(a:1)
|
597
|
+
end
|
677
598
|
|
678
|
-
|
679
|
-
|
680
|
-
|
599
|
+
let(:operation) do
|
600
|
+
collection.find_one_and_delete({ a: 1 })
|
601
|
+
end
|
681
602
|
|
682
|
-
|
683
|
-
|
684
|
-
|
603
|
+
let(:expectation) do
|
604
|
+
collection.find(a: 1).count
|
605
|
+
end
|
685
606
|
|
686
|
-
|
687
|
-
|
688
|
-
|
607
|
+
let(:successful_retry_value) do
|
608
|
+
0
|
609
|
+
end
|
689
610
|
|
690
|
-
|
611
|
+
let(:unsuccessful_retry_value) do
|
612
|
+
1
|
691
613
|
end
|
692
614
|
|
693
|
-
|
615
|
+
it_behaves_like 'supported retryable writes'
|
616
|
+
end
|
694
617
|
|
695
|
-
|
696
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
697
|
-
authorized_collection.insert_one(a:0)
|
698
|
-
authorized_collection.insert_one(a:0)
|
699
|
-
end
|
618
|
+
context 'when the operation is update_many' do
|
700
619
|
|
701
|
-
|
702
|
-
|
703
|
-
|
620
|
+
before do
|
621
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
622
|
+
authorized_collection.insert_one(a:0)
|
623
|
+
authorized_collection.insert_one(a:0)
|
624
|
+
end
|
704
625
|
|
705
|
-
|
706
|
-
|
707
|
-
|
626
|
+
let(:operation) do
|
627
|
+
collection.update_many({ a: 0 }, { '$set' => { a: 1 } })
|
628
|
+
end
|
708
629
|
|
709
|
-
|
710
|
-
|
711
|
-
|
630
|
+
let(:expectation) do
|
631
|
+
collection.find(a: 1).count
|
632
|
+
end
|
712
633
|
|
713
|
-
|
634
|
+
let(:unsuccessful_retry_value) do
|
635
|
+
0
|
714
636
|
end
|
715
637
|
|
716
|
-
|
638
|
+
it_behaves_like 'an operation that does not support retryable writes'
|
639
|
+
end
|
717
640
|
|
718
|
-
|
719
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
720
|
-
authorized_collection.insert_one(a:1)
|
721
|
-
authorized_collection.insert_one(a:1)
|
722
|
-
end
|
641
|
+
context 'when the operation is delete_many' do
|
723
642
|
|
724
|
-
|
725
|
-
|
726
|
-
|
643
|
+
before do
|
644
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
645
|
+
authorized_collection.insert_one(a:1)
|
646
|
+
authorized_collection.insert_one(a:1)
|
647
|
+
end
|
727
648
|
|
728
|
-
|
729
|
-
|
730
|
-
|
649
|
+
let(:operation) do
|
650
|
+
collection.delete_many(a: 1)
|
651
|
+
end
|
731
652
|
|
732
|
-
|
733
|
-
|
734
|
-
|
653
|
+
let(:expectation) do
|
654
|
+
collection.find(a: 1).count
|
655
|
+
end
|
735
656
|
|
736
|
-
|
657
|
+
let(:unsuccessful_retry_value) do
|
658
|
+
2
|
737
659
|
end
|
738
660
|
|
739
|
-
|
661
|
+
it_behaves_like 'an operation that does not support retryable writes'
|
662
|
+
end
|
740
663
|
|
741
|
-
|
742
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
743
|
-
authorized_collection.insert_one(a: 1)
|
744
|
-
end
|
664
|
+
context 'when the operation is a bulk write' do
|
745
665
|
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
end
|
666
|
+
before do
|
667
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
668
|
+
authorized_collection.insert_one(a: 1)
|
669
|
+
end
|
751
670
|
|
752
|
-
|
753
|
-
|
754
|
-
|
671
|
+
let(:operation) do
|
672
|
+
collection.bulk_write([{ delete_one: { filter: { a: 1 } } },
|
673
|
+
{ insert_one: { a: 1 } },
|
674
|
+
{ insert_one: { a: 1 } }])
|
675
|
+
end
|
755
676
|
|
756
|
-
|
757
|
-
|
758
|
-
|
677
|
+
let(:expectation) do
|
678
|
+
collection.find(a: 1).count
|
679
|
+
end
|
759
680
|
|
760
|
-
|
761
|
-
|
762
|
-
|
681
|
+
let(:successful_retry_value) do
|
682
|
+
2
|
683
|
+
end
|
763
684
|
|
764
|
-
|
685
|
+
let(:unsuccessful_retry_value) do
|
686
|
+
1
|
765
687
|
end
|
766
688
|
|
767
|
-
|
689
|
+
it_behaves_like 'supported retryable writes'
|
690
|
+
end
|
768
691
|
|
769
|
-
|
770
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
771
|
-
authorized_collection.insert_one(a:1)
|
772
|
-
authorized_collection.insert_one(a:1)
|
773
|
-
end
|
692
|
+
context 'when the operation is bulk write including delete_many' do
|
774
693
|
|
775
|
-
|
776
|
-
|
777
|
-
|
694
|
+
before do
|
695
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
696
|
+
authorized_collection.insert_one(a:1)
|
697
|
+
authorized_collection.insert_one(a:1)
|
698
|
+
end
|
778
699
|
|
779
|
-
|
780
|
-
|
781
|
-
|
700
|
+
let(:operation) do
|
701
|
+
collection.bulk_write([{ delete_many: { filter: { a: 1 } } }])
|
702
|
+
end
|
782
703
|
|
783
|
-
|
784
|
-
|
785
|
-
|
704
|
+
let(:expectation) do
|
705
|
+
collection.find(a: 1).count
|
706
|
+
end
|
786
707
|
|
787
|
-
|
708
|
+
let(:unsuccessful_retry_value) do
|
709
|
+
2
|
788
710
|
end
|
789
711
|
|
790
|
-
|
712
|
+
it_behaves_like 'an operation that does not support retryable writes'
|
713
|
+
end
|
791
714
|
|
792
|
-
|
793
|
-
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
794
|
-
authorized_collection.insert_one(a:0)
|
795
|
-
authorized_collection.insert_one(a:0)
|
796
|
-
end
|
715
|
+
context 'when the operation is bulk write including update_many' do
|
797
716
|
|
798
|
-
|
799
|
-
|
800
|
-
|
717
|
+
before do
|
718
|
+
# Account for when the collection has unacknowledged write concern and use authorized_collection here.
|
719
|
+
authorized_collection.insert_one(a:0)
|
720
|
+
authorized_collection.insert_one(a:0)
|
721
|
+
end
|
801
722
|
|
802
|
-
|
803
|
-
|
804
|
-
|
723
|
+
let(:operation) do
|
724
|
+
collection.bulk_write([{ update_many: { filter: { a: 0 }, update: { a: 1 } } }])
|
725
|
+
end
|
805
726
|
|
806
|
-
|
807
|
-
|
808
|
-
|
727
|
+
let(:expectation) do
|
728
|
+
collection.find(a: 1).count
|
729
|
+
end
|
809
730
|
|
810
|
-
|
731
|
+
let(:unsuccessful_retry_value) do
|
732
|
+
0
|
811
733
|
end
|
734
|
+
|
735
|
+
it_behaves_like 'an operation that does not support retryable writes'
|
812
736
|
end
|
813
737
|
end
|