mongo 2.7.0 → 2.7.1

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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +39 -14
  5. data/Rakefile +1 -0
  6. data/lib/mongo/auth.rb +4 -1
  7. data/lib/mongo/client.rb +4 -3
  8. data/lib/mongo/cluster.rb +1 -1
  9. data/lib/mongo/collection/view/readable.rb +5 -2
  10. data/lib/mongo/database.rb +1 -0
  11. data/lib/mongo/error/invalid_server_preference.rb +1 -0
  12. data/lib/mongo/error/operation_failure.rb +10 -0
  13. data/lib/mongo/error/parser.rb +10 -0
  14. data/lib/mongo/event.rb +1 -2
  15. data/lib/mongo/operation/result.rb +4 -1
  16. data/lib/mongo/operation/shared/executable_transaction_label.rb +3 -1
  17. data/lib/mongo/operation/shared/sessions_supported.rb +1 -1
  18. data/lib/mongo/protocol/msg.rb +1 -1
  19. data/lib/mongo/protocol/query.rb +2 -2
  20. data/lib/mongo/retryable.rb +20 -6
  21. data/lib/mongo/server.rb +6 -0
  22. data/lib/mongo/server/connection.rb +4 -4
  23. data/lib/mongo/server/monitor/connection.rb +9 -5
  24. data/lib/mongo/server_selector/selectable.rb +86 -32
  25. data/lib/mongo/session.rb +98 -15
  26. data/lib/mongo/version.rb +1 -1
  27. data/spec/README.md +85 -0
  28. data/spec/integration/bulk_insert_spec.rb +1 -1
  29. data/spec/integration/change_stream_examples_spec.rb +3 -1
  30. data/spec/integration/change_stream_spec.rb +10 -14
  31. data/spec/integration/client_construction_spec.rb +1 -0
  32. data/spec/integration/command_monitoring_spec.rb +37 -1
  33. data/spec/integration/command_spec.rb +141 -0
  34. data/spec/integration/connection_spec.rb +4 -2
  35. data/spec/integration/cursor_reaping_spec.rb +1 -1
  36. data/spec/integration/docs_examples_spec.rb +1 -1
  37. data/spec/integration/retryable_writes_spec.rb +33 -42
  38. data/spec/integration/server_description_spec.rb +3 -3
  39. data/spec/integration/server_selector_spec.rb +79 -0
  40. data/spec/lite_spec_helper.rb +4 -2
  41. data/spec/mongo/address_spec.rb +8 -0
  42. data/spec/mongo/auth/cr_spec.rb +5 -2
  43. data/spec/mongo/auth/invalid_mechanism_spec.rb +11 -0
  44. data/spec/mongo/auth/scram/conversation_spec.rb +3 -2
  45. data/spec/mongo/auth/scram/negotiation_spec.rb +1 -2
  46. data/spec/mongo/auth/scram_spec.rb +11 -6
  47. data/spec/mongo/auth/user/view_spec.rb +13 -6
  48. data/spec/mongo/bulk_write_spec.rb +81 -104
  49. data/spec/mongo/client_construction_spec.rb +18 -7
  50. data/spec/mongo/client_spec.rb +11 -7
  51. data/spec/mongo/cluster_spec.rb +30 -1
  52. data/spec/mongo/collection/view/aggregation_spec.rb +18 -10
  53. data/spec/mongo/collection/view/change_stream_spec.rb +28 -8
  54. data/spec/mongo/collection/view/map_reduce_spec.rb +24 -10
  55. data/spec/mongo/collection/view/readable_spec.rb +37 -19
  56. data/spec/mongo/collection/view/writable_spec.rb +64 -32
  57. data/spec/mongo/collection/view_spec.rb +4 -2
  58. data/spec/mongo/collection_spec.rb +163 -73
  59. data/spec/mongo/cursor_spec.rb +5 -2
  60. data/spec/mongo/database_spec.rb +41 -19
  61. data/spec/mongo/error/no_server_available_spec.rb +1 -1
  62. data/spec/mongo/error/parser_spec.rb +29 -0
  63. data/spec/mongo/grid/stream/write_spec.rb +2 -1
  64. data/spec/mongo/index/view_spec.rb +42 -24
  65. data/spec/mongo/operation/delete/op_msg_spec.rb +11 -7
  66. data/spec/mongo/operation/insert/op_msg_spec.rb +10 -6
  67. data/spec/mongo/operation/update/op_msg_spec.rb +10 -6
  68. data/spec/mongo/protocol/compressed_spec.rb +1 -1
  69. data/spec/mongo/protocol/msg_spec.rb +1 -1
  70. data/spec/mongo/server/app_metadata_spec.rb +2 -1
  71. data/spec/mongo/server/connection_auth_spec.rb +1 -1
  72. data/spec/mongo/server/monitor/connection_spec.rb +42 -0
  73. data/spec/mongo/server_selector_spec.rb +17 -0
  74. data/spec/mongo/server_spec.rb +110 -0
  75. data/spec/mongo/session/session_pool_spec.rb +1 -1
  76. data/spec/mongo/session_spec.rb +1 -1
  77. data/spec/mongo/session_transaction_spec.rb +162 -1
  78. data/spec/mongo/socket/ssl_spec.rb +14 -7
  79. data/spec/mongo/uri/srv_protocol_spec.rb +41 -34
  80. data/spec/spec_helper.rb +3 -191
  81. data/spec/spec_tests/change_streams_spec.rb +3 -6
  82. data/spec/spec_tests/data/transactions/abort.yml +3 -1
  83. data/spec/spec_tests/data/transactions/commit.yml +4 -3
  84. data/spec/spec_tests/data/transactions/error-labels.yml +17 -13
  85. data/spec/spec_tests/data/transactions/read-concern.yml +611 -0
  86. data/spec/spec_tests/data/transactions/retryable-commit.yml +126 -21
  87. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +42 -39
  88. data/spec/spec_tests/data/transactions_api/callback-commits.yml +52 -50
  89. data/spec/spec_tests/data/transactions_api/callback-retry.yml +33 -31
  90. data/spec/spec_tests/data/transactions_api/commit-retry.yml +42 -39
  91. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +13 -12
  92. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +15 -26
  93. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +25 -33
  94. data/spec/spec_tests/data/transactions_api/commit.yml +44 -42
  95. data/spec/spec_tests/data/transactions_api/transaction-options.yml +25 -23
  96. data/spec/spec_tests/max_staleness_spec.rb +2 -0
  97. data/spec/spec_tests/retryable_writes_spec.rb +2 -6
  98. data/spec/spec_tests/sdam_spec.rb +2 -0
  99. data/spec/spec_tests/server_selection_spec.rb +3 -0
  100. data/spec/spec_tests/transactions_api_spec.rb +7 -1
  101. data/spec/spec_tests/transactions_spec.rb +6 -0
  102. data/spec/spec_tests/uri_options_spec.rb +4 -26
  103. data/spec/support/certificates/ca.pem +21 -16
  104. data/spec/support/certificates/client.pem +90 -90
  105. data/spec/support/certificates/client_cert.pem +21 -20
  106. data/spec/support/certificates/client_key.pem +27 -28
  107. data/spec/support/certificates/client_key_encrypted.pem +26 -26
  108. data/spec/support/certificates/crl.pem +10 -8
  109. data/spec/support/certificates/crl_client_revoked.pem +11 -10
  110. data/spec/support/certificates/server.pem +48 -33
  111. data/spec/support/change_streams.rb +12 -32
  112. data/spec/support/client_registry.rb +12 -1
  113. data/spec/support/cluster_config.rb +48 -2
  114. data/spec/support/common_shortcuts.rb +73 -7
  115. data/spec/support/connection_string.rb +0 -3
  116. data/spec/support/constraints.rb +87 -22
  117. data/spec/support/crud.rb +2 -1
  118. data/spec/support/shared/server_selector.rb +0 -28
  119. data/spec/support/shared/session.rb +25 -14
  120. data/spec/support/transactions.rb +4 -8
  121. data/spec/support/transactions/operation.rb +26 -4
  122. data/spec/support/transactions/verifier.rb +5 -2
  123. metadata +496 -488
  124. metadata.gz.sig +5 -2
  125. data/spec/support/certificates/password_protected.pem +0 -51
@@ -20,6 +20,38 @@ module Mongo
20
20
  # @since 2.0.0
21
21
  module Selectable
22
22
 
23
+ # Initialize the server selector.
24
+ #
25
+ # @example Initialize the selector.
26
+ # Mongo::ServerSelector::Secondary.new(:tag_sets => [{'dc' => 'nyc'}])
27
+ #
28
+ # @example Initialize the preference with no options.
29
+ # Mongo::ServerSelector::Secondary.new
30
+ #
31
+ # @param [ Hash ] options The server preference options.
32
+ #
33
+ # @option options [ Integer ] :local_threshold The local threshold boundary for
34
+ # nearest selection in seconds.
35
+ # @option options [ Integer ] max_staleness The maximum replication lag,
36
+ # in seconds, that a secondary can suffer and still be eligible for a read.
37
+ # A value of -1 is treated identically to nil, which is to not
38
+ # have a maximum staleness.
39
+ #
40
+ # @raise [ Error::InvalidServerPreference ] If tag sets are specified
41
+ # but not allowed.
42
+ #
43
+ # @since 2.0.0
44
+ def initialize(options = nil)
45
+ options = options ? options.dup : {}
46
+ if options[:max_staleness] == -1
47
+ options.delete(:max_staleness)
48
+ end
49
+ @options = options.freeze
50
+ @tag_sets = (options[:tag_sets] || []).freeze
51
+ @max_staleness = options[:max_staleness]
52
+ validate!
53
+ end
54
+
23
55
  # @return [ Hash ] options The options.
24
56
  attr_reader :options
25
57
 
@@ -48,34 +80,6 @@ module Mongo
48
80
  max_staleness == other.max_staleness
49
81
  end
50
82
 
51
- # Initialize the server selector.
52
- #
53
- # @example Initialize the selector.
54
- # Mongo::ServerSelector::Secondary.new(:tag_sets => [{'dc' => 'nyc'}])
55
- #
56
- # @example Initialize the preference with no options.
57
- # Mongo::ServerSelector::Secondary.new
58
- #
59
- # @param [ Hash ] options The server preference options.
60
- #
61
- # @option options [ Integer ] :local_threshold The local threshold boundary for
62
- # nearest selection in seconds.
63
- # @option options [ Integer ] max_staleness The maximum replication lag,
64
- # in seconds, that a secondary can suffer and still be eligible for a read.
65
- # A value of -1 is treated identically to nil, which is to not
66
- # have a maximum staleness.
67
- #
68
- # @raise [ Error::InvalidServerPreference ] If tag sets are specified
69
- # but not allowed.
70
- #
71
- # @since 2.0.0
72
- def initialize(options = {})
73
- @options = (options || {}).freeze
74
- @tag_sets = (options[:tag_sets] || []).freeze
75
- @max_staleness = options[:max_staleness] unless options[:max_staleness] == -1
76
- validate!
77
- end
78
-
79
83
  # Inspect the server selector.
80
84
  #
81
85
  # @example Inspect the server selector.
@@ -99,6 +103,24 @@ module Mongo
99
103
  #
100
104
  # @since 2.0.0
101
105
  def select_server(cluster, ping = nil)
106
+ if cluster.replica_set?
107
+ validate_max_staleness_value_early!
108
+ end
109
+ if cluster.addresses.empty?
110
+ if Lint.enabled?
111
+ unless cluster.servers.empty?
112
+ raise Error::LintError, "Cluster has no addresses but has servers: #{cluster.servers.map(&:inspect).join(', ')}"
113
+ end
114
+ end
115
+ msg = "Cluster has no addresses, and therefore will never have a server"
116
+ raise Error::NoServerAvailable.new(self, cluster, msg)
117
+ end
118
+ =begin Add this check in version 3.0.0
119
+ unless cluster.connected?
120
+ msg = 'Cluster is disconnected'
121
+ raise Error::NoServerAvailable.new(self, cluster, msg)
122
+ end
123
+ =end
102
124
  @local_threshold = cluster.options[:local_threshold] || LOCAL_THRESHOLD
103
125
  @server_selection_timeout = cluster.options[:server_selection_timeout] || SERVER_SELECTION_TIMEOUT
104
126
  deadline = Time.now + server_selection_timeout
@@ -134,7 +156,24 @@ module Mongo
134
156
  end
135
157
  cluster.scan!(false)
136
158
  end
137
- raise Error::NoServerAvailable.new(self, cluster)
159
+
160
+ msg = "No #{name} server is available in cluster: #{cluster.summary} " +
161
+ "with timeout=#{server_selection_timeout}, " +
162
+ "LT=#{local_threshold}"
163
+ dead_monitors = []
164
+ cluster.servers_list.each do |server|
165
+ thread = server.monitor.instance_variable_get('@thread')
166
+ if thread.nil? || !thread.alive?
167
+ dead_monitors << server
168
+ end
169
+ end
170
+ if dead_monitors.any?
171
+ msg += ". The following servers have dead monitor threads: #{dead_monitors.map(&:summary).join(', ')}"
172
+ end
173
+ unless cluster.connected?
174
+ msg += ". The cluster is disconnected (client may have been closed)"
175
+ end
176
+ raise Error::NoServerAvailable.new(self, cluster, msg)
138
177
  end
139
178
 
140
179
  # Get the timeout for server selection.
@@ -292,12 +331,27 @@ module Mongo
292
331
  end
293
332
  end
294
333
 
334
+ def validate_max_staleness_value_early!
335
+ if @max_staleness
336
+ unless @max_staleness >= SMALLEST_MAX_STALENESS_SECONDS
337
+ msg = "`max_staleness` value (#{@max_staleness}) is too small - it must be at least " +
338
+ "`Mongo::ServerSelector::SMALLEST_MAX_STALENESS_SECONDS` (#{ServerSelector::SMALLEST_MAX_STALENESS_SECONDS})"
339
+ raise Error::InvalidServerPreference.new(msg)
340
+ end
341
+ end
342
+ end
343
+
295
344
  def validate_max_staleness_value!(cluster)
296
345
  if @max_staleness
297
346
  heartbeat_frequency_seconds = cluster.options[:heartbeat_frequency] || Server::Monitor::HEARTBEAT_FREQUENCY
298
- unless @max_staleness >= [ SMALLEST_MAX_STALENESS_SECONDS,
299
- (heartbeat_frequency_seconds + Cluster::IDLE_WRITE_PERIOD_SECONDS) ].max
300
- raise Error::InvalidServerPreference.new(Error::InvalidServerPreference::INVALID_MAX_STALENESS)
347
+ unless @max_staleness >= [
348
+ SMALLEST_MAX_STALENESS_SECONDS,
349
+ min_cluster_staleness = heartbeat_frequency_seconds + Cluster::IDLE_WRITE_PERIOD_SECONDS,
350
+ ].max
351
+ msg = "`max_staleness` value (#{@max_staleness}) is too small - it must be at least " +
352
+ "`Mongo::ServerSelector::SMALLEST_MAX_STALENESS_SECONDS` (#{ServerSelector::SMALLEST_MAX_STALENESS_SECONDS}) and (the cluster's heartbeat_frequency " +
353
+ "setting + `Mongo::Cluster::IDLE_WRITE_PERIOD_SECONDS`) (#{min_cluster_staleness})"
354
+ raise Error::InvalidServerPreference.new(msg)
301
355
  end
302
356
  end
303
357
  end
@@ -24,6 +24,7 @@ module Mongo
24
24
  class Session
25
25
  extend Forwardable
26
26
  include Retryable
27
+ include Loggable
27
28
 
28
29
  # Get the options for this session.
29
30
  #
@@ -113,6 +114,13 @@ module Mongo
113
114
  # @param [ Client ] client The client through which this session is created.
114
115
  # @param [ Hash ] options The options for this session.
115
116
  #
117
+ # @option options [ true|false ] :causal_consistency Whether to enable
118
+ # causal consistency for this session.
119
+ # @option options [ Hash ] :default_transaction_options Options to pass
120
+ # to start_transaction by default, can contain any of the options that
121
+ # start_transaction accepts.
122
+ # @option options [ true|false ] :implicit For internal driver use only -
123
+ # specifies whether the session is implicit.
116
124
  # @option options [ Hash ] :read_preference The read preference options hash,
117
125
  # with the following optional keys:
118
126
  # - *:mode* -- the read preference as a string or symbol; valid values are
@@ -264,9 +272,28 @@ module Mongo
264
272
  end
265
273
 
266
274
  # The read concern should be added to any command that starts a transaction.
267
- if starting_transaction? && txn_read_concern
268
- c[:readConcern] ||= {}
269
- c[:readConcern].merge!(txn_read_concern)
275
+ if starting_transaction?
276
+ # https://jira.mongodb.org/browse/SPEC-1161: transaction's
277
+ # read concern overrides collection/database/client read concerns,
278
+ # even if transaction's read concern is not set.
279
+ # Read concern here is the one sent to the server and may
280
+ # include afterClusterTime.
281
+ if rc = c[:readConcern]
282
+ rc = rc.dup
283
+ rc.delete(:level)
284
+ end
285
+ if txn_read_concern
286
+ if rc
287
+ rc.update(txn_read_concern)
288
+ else
289
+ rc = txn_read_concern.dup
290
+ end
291
+ end
292
+ if rc.nil? || rc.empty?
293
+ c.delete(:readConcern)
294
+ else
295
+ c[:readConcern ] = rc
296
+ end
270
297
  end
271
298
 
272
299
  # We need to send the read concern level as a string rather than a symbol.
@@ -275,8 +302,15 @@ module Mongo
275
302
  end
276
303
 
277
304
  # The write concern should be added to any abortTransaction or commitTransaction command.
278
- if (c[:abortTransaction] || c[:commitTransaction]) && txn_write_concern
279
- c[:writeConcern] = txn_write_concern
305
+ if (c[:abortTransaction] || c[:commitTransaction])
306
+ if @already_committed
307
+ wc = BSON::Document.new(c[:writeConcern] || txn_write_concern || {})
308
+ wc.merge!(w: :majority)
309
+ wc[:wtimeout] ||= 10000
310
+ c[:writeConcern] = wc
311
+ elsif txn_write_concern
312
+ c[:writeConcern] ||= txn_write_concern
313
+ end
280
314
  end
281
315
 
282
316
  # A non-numeric write concern w value needs to be sent as a string rather than a symbol.
@@ -544,6 +578,7 @@ module Mongo
544
578
  end
545
579
 
546
580
  @state = STARTING_TRANSACTION_STATE
581
+ @already_committed = false
547
582
  end
548
583
 
549
584
  # Commit the currently active transaction on the session.
@@ -574,6 +609,7 @@ module Mongo
574
609
  # operation again, so we revert the session to the previous state.
575
610
  if within_states?(TRANSACTION_COMMITTED_STATE)
576
611
  @state = @last_commit_skipped ? STARTING_TRANSACTION_STATE : TRANSACTION_IN_PROGRESS_STATE
612
+ @already_committed = true
577
613
  end
578
614
 
579
615
  if starting_transaction?
@@ -585,7 +621,16 @@ module Mongo
585
621
  if write_concern && !write_concern.is_a?(WriteConcern::Base)
586
622
  write_concern = WriteConcern.get(write_concern)
587
623
  end
588
- write_with_retry(self, write_concern, true) do |server, txn_num|
624
+ write_with_retry(self, write_concern, true) do |server, txn_num, is_retry|
625
+ if is_retry
626
+ if write_concern
627
+ wco = write_concern.options.merge(w: :majority)
628
+ wco[:wtimeout] ||= 10000
629
+ write_concern = WriteConcern.get(wco)
630
+ else
631
+ write_concern = WriteConcern.get(w: :majority, wtimeout: 10000)
632
+ end
633
+ end
589
634
  Operation::Command.new(
590
635
  selector: { commitTransaction: 1 },
591
636
  db_name: 'admin',
@@ -652,6 +697,9 @@ module Mongo
652
697
  raise
653
698
  rescue Mongo::Error
654
699
  @state = TRANSACTION_ABORTED_STATE
700
+ rescue Exception
701
+ @state = TRANSACTION_ABORTED_STATE
702
+ raise
655
703
  end
656
704
  end
657
705
 
@@ -687,15 +735,16 @@ module Mongo
687
735
  # with_transaction. Exceptions derived from Mongo::Error may be
688
736
  # handled by with_transaction, resulting in retries of the process.
689
737
  #
690
- # The number of retries and the total time taken by with_transaction is
691
- # not specified by the driver. The driver only guarantees that the number
692
- # of retries attempted will be finite, i.e., that it will stop retrying
693
- # at some point. The number of retries and the time allowed for the retries
694
- # is subject to change in future versions of the driver. Applications that
695
- # require known performance characteristics (for example, when servicing
696
- # web requests in an application with a fixed number of servers/workers/threads)
697
- # are encouraged to explicitly limit the time they allow for with_transaction
698
- # calls.
738
+ # Currently, with_transaction will retry commits and block invocations
739
+ # until at least 120 seconds have passed since with_transaction started
740
+ # executing. This timeout is not configurable and may change in a future
741
+ # driver version.
742
+ #
743
+ # @note with_transaction contains a loop, therefore the if with_transaction
744
+ # itself is placed in a loop, its block should not call next or break to
745
+ # control the outer loop because this will instead affect the loop in
746
+ # with_transaction. The driver will warn and abort the transaction
747
+ # if it detects this situation.
699
748
  #
700
749
  # @example Execute a statement in a transaction
701
750
  # session.with_transaction(write_concern: {w: :majority}) do
@@ -721,17 +770,27 @@ module Mongo
721
770
  #
722
771
  # @since 2.7.0
723
772
  def with_transaction(options=nil)
773
+ # Non-configurable 120 second timeout for the entire operation
774
+ deadline = Time.now + 120
775
+ transaction_in_progress = false
724
776
  loop do
725
777
  commit_options = {}
726
778
  if options
727
779
  commit_options[:write_concern] = options[:write_concern]
728
780
  end
729
781
  start_transaction(options)
782
+ transaction_in_progress = true
730
783
  begin
731
784
  rv = yield self
732
785
  rescue Exception => e
733
786
  if within_states?(STARTING_TRANSACTION_STATE, TRANSACTION_IN_PROGRESS_STATE)
734
787
  abort_transaction
788
+ transaction_in_progress = false
789
+ end
790
+
791
+ if Time.now >= deadline
792
+ transaction_in_progress = false
793
+ raise
735
794
  end
736
795
 
737
796
  if e.is_a?(Mongo::Error) && e.label?(Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL)
@@ -741,14 +800,24 @@ module Mongo
741
800
  raise
742
801
  else
743
802
  if within_states?(TRANSACTION_ABORTED_STATE, NO_TRANSACTION_STATE, TRANSACTION_COMMITTED_STATE)
803
+ transaction_in_progress = false
744
804
  return rv
745
805
  end
746
806
 
747
807
  begin
748
808
  commit_transaction(commit_options)
809
+ transaction_in_progress = false
749
810
  return rv
750
811
  rescue Mongo::Error => e
751
812
  if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
813
+ # WriteConcernFailed
814
+ if e.is_a?(Mongo::Error::OperationFailure) && e.code == 64 && e.wtimeout?
815
+ raise
816
+ end
817
+ if Time.now >= deadline
818
+ transaction_in_progress = false
819
+ raise
820
+ end
752
821
  wc_options = case v = commit_options[:write_concern]
753
822
  when WriteConcern::Base
754
823
  v.options
@@ -760,13 +829,26 @@ module Mongo
760
829
  commit_options[:write_concern] = wc_options.merge(w: :majority)
761
830
  retry
762
831
  elsif e.label?(Mongo::Error::TRANSIENT_TRANSACTION_ERROR_LABEL)
832
+ if Time.now >= deadline
833
+ transaction_in_progress = false
834
+ raise
835
+ end
763
836
  next
764
837
  else
838
+ transaction_in_progress = false
765
839
  raise
766
840
  end
767
841
  end
768
842
  end
769
843
  end
844
+ ensure
845
+ if transaction_in_progress
846
+ log_warn('with_transaction callback altered with_transaction loop, aborting transaction')
847
+ begin
848
+ abort_transaction
849
+ rescue Error::OperationFailure, Error::InvalidTransactionOperation
850
+ end
851
+ end
770
852
  end
771
853
 
772
854
  # Get the read preference the session will use in the currently
@@ -809,6 +891,7 @@ module Mongo
809
891
  end
810
892
 
811
893
  def txn_read_concern
894
+ # Read concern is inherited from client but not db or collection.
812
895
  txn_options && txn_options[:read_concern] || @client.read_concern
813
896
  end
814
897
 
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.7.0'.freeze
20
+ VERSION = '2.7.1'.freeze
21
21
  end
@@ -0,0 +1,85 @@
1
+ The tests run against a MongoDB cluster which is
2
+ configured and started externally to the test suite. This allows
3
+ running the entire test suite against, for example, a standalone
4
+ mongod as well as a replica set. The flip side to this is the
5
+ test suite will not work without a running mongo cluster, and
6
+ tests which are not applicable to or cannot be performed on the
7
+ running mongo cluster are skipped.
8
+
9
+ Not only does the test suite require an externally launched cluster,
10
+ the test suite must also be told how the cluster is configured
11
+ via MONGODB_URI, TOPOLOGY, MONGODB_ADDRESSES, RS_ENABLED, RS_NAME and/or
12
+ SHARDED_ENABLED environment variables.
13
+
14
+ The test suite attempts to provide diagnostics when it is not able to
15
+ connect to the cluster it is configured to use.
16
+
17
+ Additionally some of the tests assume that the seed list (given in
18
+ MONGODB_URI or MONGODB_ADDRESSES) encompasses all servers in the cluster,
19
+ and will fail when MONGODB_URI includes only one host of a replica set.
20
+ It is best to include all hosts of the cluster in MONGODB_URI and
21
+ MONGODB_ADDRESSES.
22
+
23
+ It is best to have the test suite configured to connect to exactly
24
+ the hostnames configured in the cluster. If, for example, the test suite
25
+ is configured to use IP addresses but the cluster is configured with
26
+ hostnames, the tests should still work (by using SDAM to discover correct
27
+ cluster configuration) but will spend a significant amount of extra time
28
+ on server discovery.
29
+
30
+ In order to run spec tests, the mongo cluster needs to have fail points
31
+ enabled. This is accomplished by starting mongod with the following option:
32
+ --setParameter enableTestCommands=1
33
+
34
+ Use the following environment variables to configure the tests:
35
+
36
+ CLIENT_DEBUG: Show debug messages from the client.
37
+
38
+ CLIENT_DEBUG=1
39
+
40
+ MONGODB_URI: Connection string to use. This must be a valid MongoDB URI;
41
+ mongodb:// and mongodb+srv:// are both supported.
42
+ RS_ENABLED and SHARDED_ENABLED are NOT honored if using MONGODB_URI -
43
+ specify replica set name in the URI and to specify a sharded topology
44
+ set TOPOLOGY=sharded_cluster environment variable.
45
+
46
+ MONGODB_URI=mongodb://127.0.0.1:27001/?replicaSet=test
47
+ MONGODB_URI=mongodb://127.0.0.1:27001,127.0.0.1:27002/ TOPOLOGY=sharded_cluster
48
+
49
+ MONGODB_ADDRESSES: Specify addresses to connect to. Use RS_ENABLED,
50
+ RS_NAME and SHARDED_ENABLED to configure the topology.
51
+
52
+ MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018
53
+ MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018 RS_ENABLED=1
54
+ MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018 RS_ENABLED=1 RS_NAME=test
55
+ MONGODB_ADDRESSES=127.0.0.1:27017,127.0.0.1:27018 SHARDED_ENABLED=1
56
+
57
+ RS_ENABLED: Instruct the test suite to connect to a replica set.
58
+ RS_ENABLED is only honored when not using MONGODB_URI; to connect to a
59
+ replica set with MONGODB_URI, specify the replica set name in the URI
60
+ (despite the Ruby driver performing topology discovery by default, it
61
+ doesn't do so in the test suite).
62
+ RS_NAME can be given to specify the replica set name; the default is
63
+ ruby-driver-rs.
64
+
65
+ RS_ENABLED=1
66
+ RS_ENABLED=1 RS_NAME=test
67
+
68
+ SHARDED_ENABLED: Instruct the test suite to connect to the sharded cluster.
69
+ Set MONGODB_URI appropriately as well.
70
+
71
+ SHARDED_ENABLED=1
72
+
73
+ SSL_ENABLED: Instruct the test suite to connect to the cluster via SSL.
74
+
75
+ SSL_ENABLED=1
76
+ # Also acceptable:
77
+ SSL=ssl
78
+
79
+ Note: SSL can also be enabled by giving ssl=true in the MONGODB_URI options.
80
+
81
+ EXTERNAL_DISABLED: Run the tests without making any external connections
82
+ (for example, external connections are required to test DNS seedlists and SRV
83
+ URIs).
84
+
85
+ EXTERNAL_DISABLED=true