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
@@ -95,4 +95,131 @@ describe Mongo::Error::Parser do
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
98
|
+
|
99
|
+
describe '#code' do
|
100
|
+
let(:parser) do
|
101
|
+
described_class.new(document)
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when document contains code' do
|
105
|
+
let(:document) do
|
106
|
+
{ 'ok' => 0, 'errmsg' => 'not master', 'code' => 10107, 'codeName' => 'NotMaster' }
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'returns the code' do
|
110
|
+
expect(parser.code).to eq(10107)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'when document does not contain code' do
|
115
|
+
let(:document) do
|
116
|
+
{ 'ok' => 0, 'errmsg' => 'not master' }
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'returns nil' do
|
120
|
+
expect(parser.code).to eq(nil)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'when the document contains a writeConcernError with a code' do
|
125
|
+
|
126
|
+
let(:document) do
|
127
|
+
{ 'writeConcernError' => { 'code' => 100, 'errmsg' => 'Not enough data-bearing nodes' } }
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'returns the code' do
|
131
|
+
expect(parser.code).to eq(100)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when the document contains a writeConcernError without a code' do
|
136
|
+
|
137
|
+
let(:document) do
|
138
|
+
{ 'writeConcernError' => { 'errmsg' => 'Not enough data-bearing nodes' } }
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'returns nil' do
|
142
|
+
expect(parser.code).to be nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#code_name' do
|
148
|
+
let(:parser) do
|
149
|
+
described_class.new(document)
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'when document contains code name' do
|
153
|
+
let(:document) do
|
154
|
+
{ 'ok' => 0, 'errmsg' => 'not master', 'code' => 10107, 'codeName' => 'NotMaster' }
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'returns the code name' do
|
158
|
+
expect(parser.code_name).to eq('NotMaster')
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'when document does not contain code name' do
|
163
|
+
let(:document) do
|
164
|
+
{ 'ok' => 0, 'errmsg' => 'not master' }
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'returns nil' do
|
168
|
+
expect(parser.code_name).to eq(nil)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'when the document contains a writeConcernError with a code' do
|
173
|
+
|
174
|
+
let(:document) do
|
175
|
+
{ 'writeConcernError' => { 'code' => 100, 'codeName' => 'CannotSatisfyWriteConcern',
|
176
|
+
'errmsg' => 'Not enough data-bearing nodes' } }
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'returns the code name' do
|
180
|
+
expect(parser.code_name).to eq('CannotSatisfyWriteConcern')
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'when the document contains a writeConcernError without a code' do
|
185
|
+
|
186
|
+
let(:document) do
|
187
|
+
{ 'writeConcernError' => { 'code' => 100, 'errmsg' => 'Not enough data-bearing nodes' } }
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'returns nil' do
|
191
|
+
expect(parser.code_name).to be nil
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '#document' do
|
197
|
+
let(:parser) do
|
198
|
+
described_class.new(document)
|
199
|
+
end
|
200
|
+
|
201
|
+
let(:document) do
|
202
|
+
{ 'ok' => 0, 'errmsg' => 'not master', 'code' => 10107, 'codeName' => 'NotMaster' }
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'returns the document' do
|
206
|
+
expect(parser.document).to eq(document)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe '#replies' do
|
211
|
+
let(:parser) do
|
212
|
+
described_class.new(document)
|
213
|
+
end
|
214
|
+
|
215
|
+
context 'when there are no replies' do
|
216
|
+
let(:document) do
|
217
|
+
{ 'ok' => 0, 'errmsg' => 'not master', 'code' => 10107, 'codeName' => 'NotMaster' }
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'returns nil' do
|
221
|
+
expect(parser.replies).to eq(nil)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
98
225
|
end
|
@@ -98,6 +98,38 @@ describe Mongo::Grid::FSBucket do
|
|
98
98
|
expect(stream.write_concern.options).to eq(Mongo::WriteConcern.get(options[:write]).options)
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
context 'when disable_md5 is not specified' do
|
103
|
+
|
104
|
+
it 'does not set the option on the write stream' do
|
105
|
+
expect(stream.options[:disable_md5]).to be_nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'when disable_md5 is specified' do
|
110
|
+
|
111
|
+
context 'when disable_md5 is true' do
|
112
|
+
|
113
|
+
let(:options) do
|
114
|
+
{ disable_md5: true }
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'passes the option to the write stream' do
|
118
|
+
expect(stream.options[:disable_md5]).to be(true)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'when disable_md5 is false' do
|
123
|
+
|
124
|
+
let(:options) do
|
125
|
+
{ disable_md5: false }
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'passes the option to the write stream' do
|
129
|
+
expect(stream.options[:disable_md5]).to be(false)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
101
133
|
end
|
102
134
|
end
|
103
135
|
end
|
@@ -27,7 +27,7 @@ describe Mongo::Grid::FSBucket::Stream::Write do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
let(:options) do
|
30
|
-
{ filename: filename }.merge(extra_options)
|
30
|
+
{ filename: filename }.merge(extra_options).merge(fs.options)
|
31
31
|
end
|
32
32
|
|
33
33
|
after do
|
@@ -53,6 +53,45 @@ describe Mongo::Grid::FSBucket::Stream::Write do
|
|
53
53
|
expect(stream.close).to be_a(BSON::ObjectId)
|
54
54
|
end
|
55
55
|
|
56
|
+
context 'when the fs does not have disable_md5 specified' do
|
57
|
+
|
58
|
+
it 'sets an md5 for the file' do
|
59
|
+
stream.send(:file_info).to_bson
|
60
|
+
expect(stream.send(:file_info).document[:md5].size).to eq(32)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when the fs has disable_md5 specified' do
|
65
|
+
|
66
|
+
before do
|
67
|
+
stream.send(:file_info).to_bson
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when disable_md5 is true' do
|
71
|
+
|
72
|
+
let(:fs_options) do
|
73
|
+
{ disable_md5: true }
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'does not set an md5 for the file' do
|
77
|
+
expect(stream.send(:file_info).document.has_key?(:md5)). to be(false)
|
78
|
+
expect(stream.send(:file_info).document[:md5]). to be_nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when disabled_md5 is false' do
|
83
|
+
|
84
|
+
let(:fs_options) do
|
85
|
+
{ disable_md5: false }
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'sets an md5 for the file' do
|
89
|
+
stream.send(:file_info).to_bson
|
90
|
+
expect(stream.send(:file_info).document[:md5].size).to eq(32)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
56
95
|
context 'when the fs has a write concern', if: standalone? do
|
57
96
|
|
58
97
|
let(:fs_options) do
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Monitoring::Event::CommandFailed do
|
4
|
+
|
5
|
+
let(:address) do
|
6
|
+
Mongo::Address.new('127.0.0.1:27017')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#command_name' do
|
10
|
+
context 'when command_name is given as a string' do
|
11
|
+
let(:event) do
|
12
|
+
described_class.new('find', 'admin', address, 1, 2, 'Uh oh', nil, 0.5)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'is a string' do
|
16
|
+
expect(event.command_name).to eql('find')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when command_name is given as a symbol' do
|
21
|
+
let(:event) do
|
22
|
+
described_class.new(:find, 'admin', address, 1, 2, 'Uh oh', nil, 0.5)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'is a string' do
|
26
|
+
expect(event.command_name).to eql('find')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,11 +2,11 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongo::Monitoring::Event::CommandStarted do
|
4
4
|
|
5
|
-
|
5
|
+
let(:address) do
|
6
|
+
Mongo::Address.new('127.0.0.1:27017')
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
Mongo::Address.new('127.0.0.1:27017')
|
9
|
-
end
|
9
|
+
describe '#initialize' do
|
10
10
|
|
11
11
|
let(:command) do
|
12
12
|
BSON::Document.new(test: 'value')
|
@@ -23,4 +23,26 @@ describe Mongo::Monitoring::Event::CommandStarted do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
describe '#command_name' do
|
28
|
+
context 'when command_name is given as a string' do
|
29
|
+
let(:event) do
|
30
|
+
described_class.new('find', 'admin', address, 1, 2, {})
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'is a string' do
|
34
|
+
expect(event.command_name).to eql('find')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when command_name is given as a symbol' do
|
39
|
+
let(:event) do
|
40
|
+
described_class.new(:find, 'admin', address, 1, 2, {})
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'is a string' do
|
44
|
+
expect(event.command_name).to eql('find')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
26
48
|
end
|
@@ -2,15 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongo::Monitoring::Event::CommandSucceeded do
|
4
4
|
|
5
|
-
|
5
|
+
let(:address) do
|
6
|
+
Mongo::Address.new('127.0.0.1:27017')
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
let(:reply) do
|
10
|
+
BSON::Document.new(test: 'value')
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
BSON::Document.new(test: 'value')
|
13
|
-
end
|
13
|
+
describe '#initialize' do
|
14
14
|
|
15
15
|
context 'when the reply should be redacted' do
|
16
16
|
|
@@ -23,4 +23,26 @@ describe Mongo::Monitoring::Event::CommandSucceeded do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
describe '#command_name' do
|
28
|
+
context 'when command_name is given as a string' do
|
29
|
+
let(:event) do
|
30
|
+
described_class.new('find', 'admin', address, 1, 2, reply, 0.5)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'is a string' do
|
34
|
+
expect(event.command_name).to eql('find')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when command_name is given as a symbol' do
|
39
|
+
let(:event) do
|
40
|
+
described_class.new(:find, 'admin', address, 1, 2, reply, 0.5)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'is a string' do
|
44
|
+
expect(event.command_name).to eql('find')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
26
48
|
end
|
@@ -85,12 +85,37 @@ describe Mongo::Monitoring do
|
|
85
85
|
double('subscriber')
|
86
86
|
end
|
87
87
|
|
88
|
-
|
88
|
+
it 'subscribes to the topic' do
|
89
89
|
monitoring.subscribe('topic', subscriber)
|
90
|
+
expect(monitoring.subscribers['topic']).to eq([ subscriber ])
|
90
91
|
end
|
91
92
|
|
92
|
-
it 'subscribes to the topic' do
|
93
|
-
|
93
|
+
it 'subscribes to the topic twice' do
|
94
|
+
monitoring.subscribe('topic', subscriber)
|
95
|
+
monitoring.subscribe('topic', subscriber)
|
96
|
+
expect(monitoring.subscribers['topic']).to eq([ subscriber, subscriber ])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#unsubscribe' do
|
101
|
+
|
102
|
+
let(:monitoring) do
|
103
|
+
described_class.new(monitoring: false)
|
104
|
+
end
|
105
|
+
|
106
|
+
let(:subscriber) do
|
107
|
+
double('subscriber')
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'unsubscribes from the topic' do
|
111
|
+
monitoring.subscribe('topic', subscriber)
|
112
|
+
monitoring.unsubscribe('topic', subscriber)
|
113
|
+
expect(monitoring.subscribers['topic']).to eq([ ])
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'unsubscribes from the topic when not subscribed' do
|
117
|
+
monitoring.unsubscribe('topic', subscriber)
|
118
|
+
expect(monitoring.subscribers['topic']).to eq([ ])
|
94
119
|
end
|
95
120
|
end
|
96
121
|
|
@@ -30,7 +30,7 @@ describe Mongo::Protocol::GetMore do
|
|
30
30
|
|
31
31
|
describe '#==' do
|
32
32
|
|
33
|
-
context 'when the other is a
|
33
|
+
context 'when the other is a getMore' do
|
34
34
|
|
35
35
|
context 'when the fields are equal' do
|
36
36
|
let(:other) do
|
@@ -83,7 +83,7 @@ describe Mongo::Protocol::GetMore do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
context 'when the other is not a
|
86
|
+
context 'when the other is not a getMore' do
|
87
87
|
let(:other) do
|
88
88
|
expect(message).not_to eq('test')
|
89
89
|
end
|
@@ -1,41 +1,74 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
class RetryableTestConsumer
|
4
|
+
include Mongo::Retryable
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
include Mongo::Retryable
|
6
|
+
attr_reader :cluster
|
7
|
+
attr_reader :operation
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
def initialize(operation, cluster)
|
10
|
+
@operation = operation
|
11
|
+
@cluster = cluster
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
14
|
+
def max_read_retries
|
15
|
+
cluster.max_read_retries
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def read_retry_interval
|
19
|
+
cluster.read_retry_interval
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def read
|
23
|
+
read_with_retry do
|
24
|
+
operation.execute
|
25
|
+
end
|
26
|
+
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
def write
|
29
|
+
# This passes a nil session and therefore triggers
|
30
|
+
# legacy_write_with_retry code path
|
31
|
+
write_with_retry(session, write_concern) do
|
32
|
+
operation.execute
|
33
|
+
end
|
34
|
+
end
|
30
35
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def retry_write_allowed_as_configured?
|
37
|
+
retry_write_allowed?(session, write_concern)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class LegacyRetryableTestConsumer < RetryableTestConsumer
|
42
|
+
def session
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def write_concern
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ModernRetryableTestConsumer < LegacyRetryableTestConsumer
|
52
|
+
include RSpec::Mocks::ExampleMethods
|
53
|
+
|
54
|
+
def session
|
55
|
+
double('session').tap do |session|
|
56
|
+
expect(session).to receive(:retry_writes?).and_return(true)
|
57
|
+
|
58
|
+
# mock everything else that is in the way
|
59
|
+
i = 1
|
60
|
+
allow(session).to receive(:next_txn_num) { i += 1 }
|
61
|
+
allow(session).to receive(:in_transaction?).and_return(false)
|
36
62
|
end
|
37
63
|
end
|
38
64
|
|
65
|
+
def write_concern
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe Mongo::Retryable do
|
71
|
+
|
39
72
|
let(:operation) do
|
40
73
|
double('operation')
|
41
74
|
end
|
@@ -49,7 +82,7 @@ describe Mongo::Retryable do
|
|
49
82
|
end
|
50
83
|
|
51
84
|
let(:retryable) do
|
52
|
-
|
85
|
+
LegacyRetryableTestConsumer.new(operation, cluster)
|
53
86
|
end
|
54
87
|
|
55
88
|
describe '#read_with_retry' do
|
@@ -132,7 +165,7 @@ describe Mongo::Retryable do
|
|
132
165
|
context 'when the operation failure is retryable' do
|
133
166
|
|
134
167
|
let(:error) do
|
135
|
-
Mongo::Error::OperationFailure.new('
|
168
|
+
Mongo::Error::OperationFailure.new('not master')
|
136
169
|
end
|
137
170
|
|
138
171
|
context 'when the retry succeeds' do
|
@@ -173,7 +206,12 @@ describe Mongo::Retryable do
|
|
173
206
|
end
|
174
207
|
end
|
175
208
|
|
176
|
-
describe '#write_with_retry' do
|
209
|
+
describe '#write_with_retry - legacy' do
|
210
|
+
|
211
|
+
before do
|
212
|
+
# Quick sanity check that the expected code path is being exercised
|
213
|
+
expect(retryable.retry_write_allowed_as_configured?).to be false
|
214
|
+
end
|
177
215
|
|
178
216
|
context 'when no exception occurs' do
|
179
217
|
|
@@ -186,32 +224,174 @@ describe Mongo::Retryable do
|
|
186
224
|
end
|
187
225
|
end
|
188
226
|
|
227
|
+
shared_examples 'executes the operation twice' do
|
228
|
+
it 'executes the operation twice' do
|
229
|
+
expect(retryable.write).to be true
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
189
233
|
context 'when a not master error occurs' do
|
190
234
|
|
191
235
|
before do
|
192
|
-
expect(operation).to receive(:execute).and_raise(
|
236
|
+
expect(operation).to receive(:execute).and_raise(
|
237
|
+
Mongo::Error::OperationFailure.new('not master')).ordered
|
193
238
|
expect(cluster).to receive(:scan!).and_return(true).ordered
|
194
239
|
expect(operation).to receive(:execute).and_return(true).ordered
|
195
240
|
end
|
196
241
|
|
197
|
-
|
198
|
-
|
242
|
+
it_behaves_like 'executes the operation twice'
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'when a node is recovering error occurs' do
|
246
|
+
|
247
|
+
before do
|
248
|
+
expect(operation).to receive(:execute).and_raise(
|
249
|
+
Mongo::Error::OperationFailure.new('node is recovering')).ordered
|
250
|
+
expect(cluster).to receive(:scan!).and_return(true).ordered
|
251
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
199
252
|
end
|
253
|
+
|
254
|
+
it_behaves_like 'executes the operation twice'
|
200
255
|
end
|
201
256
|
|
202
|
-
context 'when a
|
257
|
+
context 'when a retryable error occurs with a code' do
|
203
258
|
|
204
259
|
before do
|
205
|
-
expect(operation).to receive(:execute).and_raise(
|
260
|
+
expect(operation).to receive(:execute).and_raise(
|
261
|
+
Mongo::Error::OperationFailure.new('message missing', nil,
|
262
|
+
:code => 91, :code_name => 'ShutdownInProgress')).ordered
|
206
263
|
expect(cluster).to receive(:scan!).and_return(true).ordered
|
207
264
|
expect(operation).to receive(:execute).and_return(true).ordered
|
208
265
|
end
|
209
266
|
|
267
|
+
it_behaves_like 'executes the operation twice'
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'when a normal operation failure occurs' do
|
271
|
+
|
272
|
+
before do
|
273
|
+
expect(operation).to receive(:execute).and_raise(Mongo::Error::OperationFailure).ordered
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'raises an exception' do
|
277
|
+
expect {
|
278
|
+
retryable.write
|
279
|
+
}.to raise_error(Mongo::Error::OperationFailure)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'when a socket error occurs' do
|
284
|
+
|
285
|
+
before do
|
286
|
+
expect(operation).to receive(:execute).and_raise(
|
287
|
+
Mongo::Error::SocketError.new('socket error')).ordered
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'raises an exception' do
|
291
|
+
expect {
|
292
|
+
retryable.write
|
293
|
+
}.to raise_error(Mongo::Error::SocketError)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context 'when a socket timeout occurs' do
|
298
|
+
|
299
|
+
before do
|
300
|
+
expect(operation).to receive(:execute).and_raise(
|
301
|
+
Mongo::Error::SocketTimeoutError.new('socket timeout')).ordered
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'raises an exception' do
|
305
|
+
expect {
|
306
|
+
retryable.write
|
307
|
+
}.to raise_error(Mongo::Error::SocketTimeoutError)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'when a non-retryable exception occurs' do
|
312
|
+
|
313
|
+
before do
|
314
|
+
expect(operation).to receive(:execute).and_raise(
|
315
|
+
Mongo::Error::UnsupportedCollation.new('unsupported collation')).ordered
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'raises an exception' do
|
319
|
+
expect {
|
320
|
+
retryable.write
|
321
|
+
}.to raise_error(Mongo::Error::UnsupportedCollation)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
describe '#write_with_retry - modern' do
|
328
|
+
|
329
|
+
let(:retryable) do
|
330
|
+
ModernRetryableTestConsumer.new(operation, cluster)
|
331
|
+
end
|
332
|
+
|
333
|
+
before do
|
334
|
+
# Quick sanity check that the expected code path is being exercised
|
335
|
+
expect(retryable.retry_write_allowed_as_configured?).to be true
|
336
|
+
|
337
|
+
allow(server_selector).to receive(:retry_writes?).and_return(true)
|
338
|
+
allow(cluster).to receive(:scan!)
|
339
|
+
end
|
340
|
+
|
341
|
+
context 'when no exception occurs' do
|
342
|
+
|
343
|
+
before do
|
344
|
+
expect(operation).to receive(:execute).and_return(true)
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'executes the operation once' do
|
348
|
+
expect(retryable.write).to be true
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
shared_examples 'executes the operation twice' do
|
210
353
|
it 'executes the operation twice' do
|
211
354
|
expect(retryable.write).to be true
|
212
355
|
end
|
213
356
|
end
|
214
357
|
|
358
|
+
context 'when a not master error occurs' do
|
359
|
+
|
360
|
+
before do
|
361
|
+
expect(operation).to receive(:execute).and_raise(
|
362
|
+
Mongo::Error::OperationFailure.new('not master')).ordered
|
363
|
+
expect(cluster).to receive(:scan!).and_return(true).ordered
|
364
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
365
|
+
end
|
366
|
+
|
367
|
+
it_behaves_like 'executes the operation twice'
|
368
|
+
end
|
369
|
+
|
370
|
+
context 'when a node is recovering error occurs' do
|
371
|
+
|
372
|
+
before do
|
373
|
+
expect(operation).to receive(:execute).and_raise(
|
374
|
+
Mongo::Error::OperationFailure.new('node is recovering')).ordered
|
375
|
+
expect(cluster).to receive(:scan!).and_return(true).ordered
|
376
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
377
|
+
end
|
378
|
+
|
379
|
+
it_behaves_like 'executes the operation twice'
|
380
|
+
end
|
381
|
+
|
382
|
+
context 'when a retryable error occurs with a code' do
|
383
|
+
|
384
|
+
before do
|
385
|
+
expect(operation).to receive(:execute).and_raise(
|
386
|
+
Mongo::Error::OperationFailure.new('message missing', nil,
|
387
|
+
:code => 91, :code_name => 'ShutdownInProgress')).ordered
|
388
|
+
expect(cluster).to receive(:scan!).and_return(true).ordered
|
389
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
390
|
+
end
|
391
|
+
|
392
|
+
it_behaves_like 'executes the operation twice'
|
393
|
+
end
|
394
|
+
|
215
395
|
context 'when a normal operation failure occurs' do
|
216
396
|
|
217
397
|
before do
|
@@ -225,5 +405,43 @@ describe Mongo::Retryable do
|
|
225
405
|
end
|
226
406
|
end
|
227
407
|
|
408
|
+
context 'when a socket error occurs' do
|
409
|
+
|
410
|
+
before do
|
411
|
+
expect(operation).to receive(:execute).and_raise(
|
412
|
+
Mongo::Error::SocketError.new('socket error')).ordered
|
413
|
+
expect(cluster).to receive(:scan!).and_return(true).ordered
|
414
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
415
|
+
end
|
416
|
+
|
417
|
+
it_behaves_like 'executes the operation twice'
|
418
|
+
end
|
419
|
+
|
420
|
+
context 'when a socket timeout occurs' do
|
421
|
+
|
422
|
+
before do
|
423
|
+
expect(operation).to receive(:execute).and_raise(
|
424
|
+
Mongo::Error::SocketTimeoutError.new('socket timeout')).ordered
|
425
|
+
expect(cluster).to receive(:scan!).and_return(true).ordered
|
426
|
+
expect(operation).to receive(:execute).and_return(true).ordered
|
427
|
+
end
|
428
|
+
|
429
|
+
it_behaves_like 'executes the operation twice'
|
430
|
+
end
|
431
|
+
|
432
|
+
context 'when a non-retryable exception occurs' do
|
433
|
+
|
434
|
+
before do
|
435
|
+
expect(operation).to receive(:execute).and_raise(
|
436
|
+
Mongo::Error::UnsupportedCollation.new('unsupported collation')).ordered
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'raises an exception' do
|
440
|
+
expect {
|
441
|
+
retryable.write
|
442
|
+
}.to raise_error(Mongo::Error::UnsupportedCollation)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
228
446
|
end
|
229
447
|
end
|