mongo 2.7.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
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