mongo 2.5.0 → 2.5.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 (99) 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 +2 -0
  5. data/Rakefile +4 -1
  6. data/lib/mongo/address.rb +2 -1
  7. data/lib/mongo/client.rb +6 -51
  8. data/lib/mongo/cluster.rb +34 -4
  9. data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -1
  10. data/lib/mongo/cluster/topology/replica_set.rb +3 -1
  11. data/lib/mongo/collection.rb +6 -6
  12. data/lib/mongo/collection/view.rb +2 -4
  13. data/lib/mongo/cursor.rb +9 -4
  14. data/lib/mongo/error.rb +2 -0
  15. data/lib/mongo/operation/uses_command_op_msg.rb +1 -1
  16. data/lib/mongo/server.rb +3 -0
  17. data/lib/mongo/server/description.rb +1 -1
  18. data/lib/mongo/server/description/features.rb +18 -12
  19. data/lib/mongo/server_selector/selectable.rb +5 -1
  20. data/lib/mongo/session.rb +38 -43
  21. data/lib/mongo/session/session_pool.rb +12 -30
  22. data/lib/mongo/socket.rb +24 -0
  23. data/lib/mongo/socket/tcp.rb +0 -1
  24. data/lib/mongo/uri.rb +26 -5
  25. data/lib/mongo/version.rb +1 -1
  26. data/spec/mongo/address_spec.rb +37 -2
  27. data/spec/mongo/bulk_write_spec.rb +4 -10
  28. data/spec/mongo/change_stream_examples_spec.rb +40 -0
  29. data/spec/mongo/client_spec.rb +47 -12
  30. data/spec/mongo/cluster/topology/replica_set_spec.rb +2 -0
  31. data/spec/mongo/collection/view/aggregation_spec.rb +2 -8
  32. data/spec/mongo/collection/view/change_stream_spec.rb +1 -5
  33. data/spec/mongo/collection/view/map_reduce_spec.rb +2 -8
  34. data/spec/mongo/collection/view/readable_spec.rb +1 -1
  35. data/spec/mongo/collection_spec.rb +11 -29
  36. data/spec/mongo/crud_spec.rb +6 -2
  37. data/spec/mongo/cursor_spec.rb +84 -1
  38. data/spec/mongo/database_spec.rb +2 -8
  39. data/spec/mongo/dns_seedlist_discovery_spec.rb +67 -63
  40. data/spec/mongo/max_staleness_spec.rb +1 -0
  41. data/spec/mongo/retryable_writes_spec.rb +7 -9
  42. data/spec/mongo/sdam_spec.rb +42 -24
  43. data/spec/mongo/server/description/features_spec.rb +3 -3
  44. data/spec/mongo/server_selection_spec.rb +2 -0
  45. data/spec/mongo/server_selector_spec.rb +2 -0
  46. data/spec/mongo/session/session_pool_spec.rb +16 -22
  47. data/spec/mongo/session_spec.rb +13 -8
  48. data/spec/mongo/uri/srv_protocol_spec.rb +481 -478
  49. data/spec/mongo/uri_spec.rb +1 -1
  50. data/spec/spec_helper.rb +11 -63
  51. data/spec/support/authorization.rb +35 -1
  52. data/spec/support/connection_string_tests/invalid-uris.yml +27 -11
  53. data/spec/support/event_subscriber.rb +66 -0
  54. data/spec/support/sdam/rs/compatible.yml +41 -0
  55. data/spec/support/sdam/rs/discover_arbiters.yml +3 -1
  56. data/spec/support/sdam/rs/discover_passives.yml +6 -2
  57. data/spec/support/sdam/rs/discover_primary.yml +3 -1
  58. data/spec/support/sdam/rs/discover_secondary.yml +3 -1
  59. data/spec/support/sdam/rs/discovery.yml +12 -4
  60. data/spec/support/sdam/rs/equal_electionids.yml +6 -2
  61. data/spec/support/sdam/rs/ghost_discovered.yml +3 -1
  62. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +3 -1
  63. data/spec/support/sdam/rs/ls_timeout.yml +169 -14
  64. data/spec/support/sdam/rs/member_reconfig.yml +6 -2
  65. data/spec/support/sdam/rs/member_standalone.yml +6 -2
  66. data/spec/support/sdam/rs/new_primary.yml +6 -2
  67. data/spec/support/sdam/rs/new_primary_new_electionid.yml +9 -3
  68. data/spec/support/sdam/rs/new_primary_new_setversion.yml +9 -3
  69. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +6 -2
  70. data/spec/support/sdam/rs/non_rs_member.yml +3 -2
  71. data/spec/support/sdam/rs/normalize_case.yml +3 -1
  72. data/spec/support/sdam/rs/null_election_id.yml +12 -4
  73. data/spec/support/sdam/rs/primary_becomes_standalone.yml +6 -4
  74. data/spec/support/sdam/rs/primary_changes_set_name.yml +6 -2
  75. data/spec/support/sdam/rs/primary_disconnect.yml +3 -1
  76. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +15 -5
  77. data/spec/support/sdam/rs/primary_disconnect_setversion.yml +15 -5
  78. data/spec/support/sdam/rs/primary_hint_from_secondary_with_mismatched_me.yml +6 -2
  79. data/spec/support/sdam/rs/primary_mismatched_me.yml +26 -37
  80. data/spec/support/sdam/rs/primary_reports_new_member.yml +12 -4
  81. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +6 -2
  82. data/spec/support/sdam/rs/primary_wrong_set_name.yml +3 -1
  83. data/spec/support/sdam/rs/response_from_removed.yml +6 -2
  84. data/spec/support/sdam/rs/rsother_discovered.yml +6 -2
  85. data/spec/support/sdam/rs/sec_not_auth.yml +6 -2
  86. data/spec/support/sdam/rs/secondary_mismatched_me.yml +26 -37
  87. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +3 -1
  88. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +6 -2
  89. data/spec/support/sdam/rs/setversion_without_electionid.yml +6 -2
  90. data/spec/support/sdam/rs/stepdown_change_set_name.yml +6 -2
  91. data/spec/support/sdam/rs/too_new.yml +41 -0
  92. data/spec/support/sdam/rs/too_old.yml +39 -0
  93. data/spec/support/sdam/rs/unexpected_mongos.yml +3 -1
  94. data/spec/support/sdam/rs/use_setversion_without_electionid.yml +9 -3
  95. data/spec/support/sdam/rs/wrong_set_name.yml +3 -1
  96. data/spec/support/server_discovery_and_monitoring.rb +13 -0
  97. data/spec/support/shared/session.rb +10 -30
  98. metadata +10 -2
  99. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a0c8476badc0a3215c3e04955d182d0f5d8eff0
4
- data.tar.gz: 8e22da76ade8734b4a58a9fbac4aa0524825800e
3
+ metadata.gz: 22155206427257fef9e634311719afb58b03f76c
4
+ data.tar.gz: c156ef4a3569277ad0c398455d7983c3e2475051
5
5
  SHA512:
6
- metadata.gz: cc6f598c936f2aff4eea3fa9d9eb00eea905912c1d2c587d6b307f3d97655d29bd5fd12dd02a6548a384fe04e82b169ff22c5d9ed7db77ec74e7073793345d27
7
- data.tar.gz: 118a7e1f0942d35672138d6a3ab0d1b3967122d14344fe7cc3645d1a3b511dfd7cf6b05ad547e2b04ee19230dd30f8978f004bddec7952c230183948e8180ceb
6
+ metadata.gz: 4252e5a66f31ee3ba496bd573b37ee08f0dd513b3d1e1b154da01c7d34dc19714fc929de7454cc4ea0415fbb44312a8b1c29cf06c1cfb20adee72e97cd917443
7
+ data.tar.gz: efb7c93290353223cfc910a383b0a0edd9f2d0cc3b6405389256f48fe1dd1ed3647449db8d07663300303ba07a25a038f46d4c2ee5b1bdc0e804890e73b698b6
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -45,6 +45,8 @@ Running Tests
45
45
 
46
46
  The driver uses RSpec as it's primary testing tool. To run all tests simple run `rspec`.
47
47
 
48
+ If you need to run the tests without making any external connections, set the ENV variable EXTERNAL_DISABLED to 'true'.
49
+
48
50
  To run a test at a specific location (where `42` is the line number), use:
49
51
 
50
52
  rspec path/to/spec.rb:42
data/Rakefile CHANGED
@@ -15,7 +15,10 @@ Bundler.require(*default_groups)
15
15
 
16
16
  require 'rspec/core/rake_task'
17
17
 
18
- RSpec::Core::RakeTask.new(:spec)
18
+ RSpec::Core::RakeTask.new(:spec) do |t|
19
+ t.rspec_opts = "--profile 5" if ENV['CI']
20
+ end
21
+
19
22
  task :default => :spec
20
23
 
21
24
  namespace :spec do
@@ -185,7 +185,8 @@ module Mongo
185
185
  error = nil
186
186
  ::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM).each do |info|
187
187
  begin
188
- res = FAMILY_MAP[info[4]].new(host, port, host)
188
+ _host = (host == LOCALHOST) ? info[3] : host
189
+ res = FAMILY_MAP[info[4]].new(_host, port, host)
189
190
  res.socket(connect_timeout, ssl_options).connect!(connect_timeout).close
190
191
  return res
191
192
  rescue IOError, SystemCallError, Error::SocketTimeoutError, Error::SocketError => e
@@ -96,8 +96,6 @@ module Mongo
96
96
  # Delegate subscription to monitoring.
97
97
  def_delegators :@monitoring, :subscribe, :unsubscribe
98
98
 
99
- def_delegators :@cluster, :logical_session_timeout
100
-
101
99
  # Determine if this client is equivalent to another object.
102
100
  #
103
101
  # @example Check client equality.
@@ -249,32 +247,14 @@ module Mongo
249
247
  # @since 2.0.0
250
248
  def initialize(addresses_or_uri, options = Options::Redacted.new)
251
249
  @monitoring = Monitoring.new(options)
252
- Session::SessionPool.create(self)
253
250
  if addresses_or_uri.is_a?(::String)
254
251
  create_from_uri(addresses_or_uri, validate_options!(options))
255
252
  else
256
253
  create_from_addresses(addresses_or_uri, validate_options!(options))
257
254
  end
258
- ObjectSpace.define_finalizer(self, self.class.finalize(@session_pool))
259
255
  yield(self) if block_given?
260
256
  end
261
257
 
262
- # Finalize the client for garbage collection. Ends all sessions in the session pool.
263
- #
264
- # @example Finalize the client.
265
- # Client.finalize(session_pool)
266
- #
267
- # @param [ Session::SessionPool ] session_pool The session pool.
268
- #
269
- # @return [ Proc ] The Finalizer.
270
- #
271
- # @since 2.5.0
272
- def self.finalize(session_pool)
273
- proc do
274
- begin; session_pool.end_sessions; rescue; end
275
- end
276
- end
277
-
278
258
  # Get an inspection of the client as a string.
279
259
  #
280
260
  # @example Inspect the client.
@@ -345,7 +325,6 @@ module Mongo
345
325
  opts = validate_options!(new_options)
346
326
  client.options.update(opts)
347
327
  Database.create(client)
348
- Session::SessionPool.create(client)
349
328
  # We can't use the same cluster if some options that would affect it
350
329
  # have changed.
351
330
  if cluster_modifying?(opts)
@@ -445,7 +424,7 @@ module Mongo
445
424
  # Start a session.
446
425
  #
447
426
  # @example Start a session.
448
- # client.start_session
427
+ # client.start_session(causal_consistency: true)
449
428
  #
450
429
  # @param [ Hash ] options The session options.
451
430
  #
@@ -456,42 +435,18 @@ module Mongo
456
435
  #
457
436
  # @since 2.5.0
458
437
  def start_session(options = {})
459
- if !sessions_supported?
460
- raise Error::InvalidSession.new(Session::SESSIONS_NOT_SUPPORTED)
461
- end
462
- Session.new(@session_pool.checkout, self, options)
438
+ cluster.send(:get_session, options.merge(implicit: false)) ||
439
+ (raise Error::InvalidSession.new(Session::SESSIONS_NOT_SUPPORTED))
463
440
  end
464
441
 
465
442
  private
466
443
 
467
444
  def get_session(options = {})
468
- if options[:session]
469
- options[:session].validate!(self)
470
- options[:session]
471
- elsif sessions_supported?
472
- Session.new(@session_pool.checkout, self, options.merge(implicit: true))
473
- end
474
- end
475
-
476
- def with_session(options = {})
477
- if options[:session]
478
- options[:session].validate!(self)
479
- yield(options[:session])
480
- elsif sessions_supported?
481
- @session_pool.with_session do |server_session|
482
- yield(Session.new(server_session, self, options))
483
- end
484
- else
485
- yield
486
- end
445
+ cluster.send(:get_session, options)
487
446
  end
488
447
 
489
- def sessions_supported?
490
- if cluster.servers.empty? && !cluster.topology.single?
491
- ServerSelector.get(mode: :primary_preferred).select_server(cluster)
492
- end
493
- !!logical_session_timeout
494
- rescue Error::NoServerAvailable
448
+ def with_session(options = {}, &block)
449
+ cluster.send(:with_session, options, &block)
495
450
  end
496
451
 
497
452
  def create_from_addresses(addresses, opts = Options::Redacted.new)
@@ -75,6 +75,11 @@ module Mongo
75
75
  # @since 2.5.0
76
76
  attr_reader :cluster_time
77
77
 
78
+ # @private
79
+ #
80
+ # @since 2.5.1
81
+ attr_reader :session_pool
82
+
78
83
  def_delegators :topology, :replica_set?, :replica_set_name, :sharded?,
79
84
  :single?, :unknown?, :member_discovered
80
85
  def_delegators :@cursor_reaper, :register_cursor, :schedule_kill_cursor, :unregister_cursor
@@ -173,6 +178,7 @@ module Mongo
173
178
  @cluster_time = nil
174
179
  @cluster_time_lock = Mutex.new
175
180
  @topology = Topology.initial(seeds, monitoring, options)
181
+ Session::SessionPool.create(self)
176
182
 
177
183
  publish_sdam_event(
178
184
  Monitoring::TOPOLOGY_OPENING,
@@ -195,7 +201,7 @@ module Mongo
195
201
  @periodic_executor = PeriodicExecutor.new(@cursor_reaper, @socket_reaper)
196
202
  @periodic_executor.run!
197
203
 
198
- ObjectSpace.define_finalizer(self, self.class.finalize(pools, @periodic_executor))
204
+ ObjectSpace.define_finalizer(self, self.class.finalize(pools, @periodic_executor, @session_pool))
199
205
  end
200
206
 
201
207
  # Finalize the cluster for garbage collection. Disconnects all the scoped
@@ -204,14 +210,16 @@ module Mongo
204
210
  # @example Finalize the cluster.
205
211
  # Cluster.finalize(pools)
206
212
  #
207
- # @param [ Hash<Address, Server::ConnectionPool> ] pools The connection
208
- # pools.
213
+ # @param [ Hash<Address, Server::ConnectionPool> ] pools The connection pools.
214
+ # @param [ PeriodicExecutor ] periodic_executor The periodic executor.
215
+ # @param [ SessionPool ] session_pool The session pool.
209
216
  #
210
217
  # @return [ Proc ] The Finalizer.
211
218
  #
212
219
  # @since 2.2.0
213
- def self.finalize(pools, periodic_executor)
220
+ def self.finalize(pools, periodic_executor, session_pool)
214
221
  proc do
222
+ session_pool.end_sessions
215
223
  periodic_executor.stop!
216
224
  pools.values.each do |pool|
217
225
  pool.disconnect!
@@ -495,6 +503,28 @@ module Mongo
495
503
 
496
504
  private
497
505
 
506
+ def get_session(options = {})
507
+ return options[:session].validate!(self) if options[:session]
508
+ if sessions_supported?
509
+ Session.new(@session_pool.checkout, self, { implicit: true }.merge(options))
510
+ end
511
+ end
512
+
513
+ def with_session(options = {})
514
+ session = get_session(options)
515
+ yield(session)
516
+ ensure
517
+ session.end_session if (session && session.implicit?)
518
+ end
519
+
520
+ def sessions_supported?
521
+ if servers.empty? && !topology.single?
522
+ ServerSelector.get(mode: :primary_preferred).select_server(self)
523
+ end
524
+ !!logical_session_timeout
525
+ rescue Error::NoServerAvailable
526
+ end
527
+
498
528
  def direct_connection?(address)
499
529
  address.seed == @topology.seed
500
530
  end
@@ -29,7 +29,7 @@ module Mongo
29
29
  # @example Initialize the socket reaper.
30
30
  # SocketReaper.new(cluster)
31
31
  #
32
- # @params [ Mongo::Cluster ] cluster The cluster whose pools' stale sockets
32
+ # @param [ Mongo::Cluster ] cluster The cluster whose pools' stale sockets
33
33
  # need to be reaped at regular intervals.
34
34
  #
35
35
  # @since 2.5.0
@@ -217,7 +217,9 @@ module Mongo
217
217
  # @since 2.0.6
218
218
  def remove_server?(description, server)
219
219
  remove_self?(description, server) ||
220
- (member_of_this_set?(description) && !description.lists_server?(server))
220
+ (member_of_this_set?(description) &&
221
+ !description.servers.empty? &&
222
+ !description.lists_server?(server))
221
223
  end
222
224
 
223
225
  # A replica set topology is not sharded.
@@ -410,23 +410,23 @@ module Mongo
410
410
  # collection.insert_one({ name: 'test' })
411
411
  #
412
412
  # @param [ Hash ] document The document to insert.
413
- # @param [ Hash ] options The insert options.
413
+ # @param [ Hash ] opts The insert options.
414
414
  #
415
- # @option options [ Session ] :session The session to use for the operation.
415
+ # @option opts [ Session ] :session The session to use for the operation.
416
416
  #
417
417
  # @return [ Result ] The database response wrapper.
418
418
  #
419
419
  # @since 2.0.0
420
- def insert_one(document, options = {})
421
- client.send(:with_session, options) do |session|
420
+ def insert_one(document, opts = {})
421
+ client.send(:with_session, opts) do |session|
422
422
  write_with_retry(session, write_concern) do |server, txn_num|
423
423
  Operation::Write::Insert.new(
424
424
  :documents => [ document ],
425
425
  :db_name => database.name,
426
426
  :coll_name => name,
427
427
  :write_concern => write_concern,
428
- :bypass_document_validation => !!options[:bypass_document_validation],
429
- :options => options,
428
+ :bypass_document_validation => !!opts[:bypass_document_validation],
429
+ :options => opts,
430
430
  :id_generator => client.options[:id_generator],
431
431
  :session => session,
432
432
  :txn_num => txn_num
@@ -199,10 +199,8 @@ module Mongo
199
199
 
200
200
  def view; self; end
201
201
 
202
- def with_session(opts = {})
203
- client.send(:with_session, @options.merge(opts)) do |session|
204
- yield(session)
205
- end
202
+ def with_session(opts = {}, &block)
203
+ client.send(:with_session, @options.merge(opts), &block)
206
204
  end
207
205
  end
208
206
  end
@@ -69,7 +69,8 @@ module Mongo
69
69
  ObjectSpace.define_finalizer(self, self.class.finalize(result.cursor_id,
70
70
  cluster,
71
71
  kill_cursors_op_spec,
72
- server))
72
+ server,
73
+ @session))
73
74
  end
74
75
 
75
76
 
@@ -87,8 +88,11 @@ module Mongo
87
88
  # @return [ Proc ] The Finalizer.
88
89
  #
89
90
  # @since 2.3.0
90
- def self.finalize(cursor_id, cluster, op_spec, server)
91
- proc { cluster.schedule_kill_cursor(cursor_id, op_spec, server) }
91
+ def self.finalize(cursor_id, cluster, op_spec, server, session)
92
+ proc do
93
+ cluster.schedule_kill_cursor(cursor_id, op_spec, server)
94
+ session.end_session if session && session.implicit?
95
+ end
92
96
  end
93
97
 
94
98
  # Get a human-readable string representation of +Cursor+.
@@ -219,7 +223,7 @@ module Mongo
219
223
  end
220
224
 
221
225
  def end_session
222
- @session.end_implicit_session if @session
226
+ @session.end_session if @session && @session.implicit?
223
227
  end
224
228
 
225
229
  def kill_cursors_operation
@@ -251,6 +255,7 @@ module Mongo
251
255
  @coll_name ||= result.namespace.sub("#{database.name}.", '') if result.namespace
252
256
  unregister if result.cursor_id == 0
253
257
  @cursor_id = result.cursor_id
258
+ end_session if !more?
254
259
  result.documents
255
260
  end
256
261
 
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'forwardable'
16
+
15
17
  module Mongo
16
18
  # Base error class for all Mongo related errors.
17
19
  #
@@ -58,7 +58,7 @@ module Mongo
58
58
  apply_session_id!(selector)
59
59
  apply_causal_consistency!(selector, server)
60
60
  end
61
- elsif session && !session.send(:implicit_session?)
61
+ elsif session && !session.implicit?
62
62
  apply_cluster_time!(selector, server)
63
63
  apply_session_id!(selector)
64
64
  apply_causal_consistency!(selector, server)
@@ -81,6 +81,9 @@ module Mongo
81
81
  :cluster_time,
82
82
  :update_cluster_time
83
83
 
84
+ def_delegators :features,
85
+ :check_driver_support!
86
+
84
87
  # Is this server equal to another?
85
88
  #
86
89
  # @example Is the server equal to the other?
@@ -264,7 +264,7 @@ module Mongo
264
264
  def initialize(address, config = {}, average_round_trip_time = 0)
265
265
  @address = address
266
266
  @config = config
267
- @features = Features.new(wire_versions, me)
267
+ @features = Features.new(wire_versions, me || @address.to_s)
268
268
  @average_round_trip_time = average_round_trip_time
269
269
  end
270
270
 
@@ -88,21 +88,27 @@ module Mongo
88
88
  # @since 2.0.0
89
89
  def initialize(server_wire_versions, address = nil)
90
90
  @server_wire_versions = server_wire_versions
91
- check_driver_support!(address) unless server_wire_versions == ZERO_RANGE
91
+ @address = address
92
92
  end
93
93
 
94
- private
95
-
96
- ZERO_RANGE = (0..0).freeze
97
-
98
- def check_driver_support!(address)
99
- if DRIVER_WIRE_VERSIONS.min > server_wire_versions.max
100
- raise Error::UnsupportedFeatures.new(SERVER_TOO_OLD % [address,
101
- server_wire_versions.max,
94
+ # Check that there is an overlap between the driver supported wire version range
95
+ # and the server wire version range.
96
+ #
97
+ # @example Verify the wire version overlap.
98
+ # features.check_driver_support!
99
+ #
100
+ # @raise [ Error::UnsupportedFeatures ] If the wire version range is not covered
101
+ # by the driver.
102
+ #
103
+ # @since 2.5.1
104
+ def check_driver_support!
105
+ if DRIVER_WIRE_VERSIONS.min > @server_wire_versions.max
106
+ raise Error::UnsupportedFeatures.new(SERVER_TOO_OLD % [@address,
107
+ @server_wire_versions.max,
102
108
  DRIVER_WIRE_VERSIONS.min])
103
- elsif DRIVER_WIRE_VERSIONS.max < server_wire_versions.min
104
- raise Error::UnsupportedFeatures.new(DRIVER_TOO_OLD % [address,
105
- server_wire_versions.min,
109
+ elsif DRIVER_WIRE_VERSIONS.max < @server_wire_versions.min
110
+ raise Error::UnsupportedFeatures.new(DRIVER_TOO_OLD % [@address,
111
+ @server_wire_versions.min,
106
112
  DRIVER_WIRE_VERSIONS.max])
107
113
  end
108
114
  end
@@ -105,8 +105,12 @@ module Mongo
105
105
  # There is no point pinging a standalone as the subsequent scan is
106
106
  # not going to change anything about the cluster.
107
107
  if ping && !cluster.single?
108
- return server if server.connectable?
108
+ if server.connectable?
109
+ server.check_driver_support!
110
+ return server
111
+ end
109
112
  else
113
+ server.check_driver_support!
110
114
  return server
111
115
  end
112
116
  end
@@ -17,7 +17,7 @@ require 'mongo/session/server_session'
17
17
 
18
18
  module Mongo
19
19
 
20
- # A logical client session representing a set of sequential operations executed
20
+ # A logical session representing a set of sequential operations executed
21
21
  # by an application that are related in some way.
22
22
  #
23
23
  # @since 2.5.0
@@ -29,10 +29,10 @@ module Mongo
29
29
  # @since 2.5.0
30
30
  attr_reader :options
31
31
 
32
- # Get the client through which this session was created.
32
+ # Get the cluster through which this session was created.
33
33
  #
34
- # @since 2.5.0
35
- attr_reader :client
34
+ # @since 2.5.1
35
+ attr_reader :cluster
36
36
 
37
37
  # The cluster time for this session.
38
38
  #
@@ -44,14 +44,13 @@ module Mongo
44
44
  # @since 2.5.0
45
45
  attr_reader :operation_time
46
46
 
47
- def_delegators :client, :cluster
48
-
49
- # Error message describing that the session was attempted to be used by a client different from the
50
- # one it was originally associated with.
47
+ # Error message indicating that the session was retrieved from a client with a different cluster than that of the
48
+ # client through which it is currently being used.
51
49
  #
52
50
  # @since 2.5.0
53
- MISMATCHED_CLUSTER_ERROR_MSG = 'The client used to create this session does not match that of client ' +
54
- 'initiating this operation. Please only use this session for operations through its parent client.'.freeze
51
+ MISMATCHED_CLUSTER_ERROR_MSG = 'The configuration of the client used to create this session does not match that ' +
52
+ 'of the client owning this operation. Please only use this session for operations through its parent ' +
53
+ 'client.'.freeze
55
54
 
56
55
  # Error message describing that the session cannot be used because it has already been ended.
57
56
  #
@@ -66,16 +65,16 @@ module Mongo
66
65
  # Initialize a Session.
67
66
  #
68
67
  # @example
69
- # Session.new(server_session, client, options)
68
+ # Session.new(server_session, cluster, options)
70
69
  #
71
- # @param [ ServerSession ] server_session The server session this client session is associated with.
72
- # @param [ Client ] client The client through which this session is created.
70
+ # @param [ ServerSession ] server_session The server session this session is associated with.
71
+ # @param [ Cluster ] cluster The cluster through which this session is created.
73
72
  # @param [ Hash ] options The options for this session.
74
73
  #
75
74
  # @since 2.5.0
76
- def initialize(server_session, client, options = {})
75
+ def initialize(server_session, cluster, options = {})
77
76
  @server_session = server_session
78
- @client = client
77
+ @cluster = cluster
79
78
  @options = options.dup.freeze
80
79
  @cluster_time = nil
81
80
  end
@@ -101,26 +100,13 @@ module Mongo
101
100
  #
102
101
  # @since 2.5.0
103
102
  def end_session
104
- if !ended? && @client
105
- @client.instance_variable_get(:@session_pool).checkin(@server_session)
106
- nil
103
+ if !ended? && @cluster
104
+ @cluster.session_pool.checkin(@server_session)
107
105
  end
108
106
  ensure
109
107
  @server_session = nil
110
108
  end
111
109
 
112
- # End this session if it's an implicit session.
113
- #
114
- # @example
115
- # session.end_implicit_session
116
- #
117
- # @return [ nil ] Always nil.
118
- #
119
- # @since 2.5.0
120
- def end_implicit_session
121
- end_session if implicit_session?
122
- end
123
-
124
110
  # Whether this session has ended.
125
111
  #
126
112
  # @example
@@ -148,18 +134,19 @@ module Mongo
148
134
  # Validate the session.
149
135
  #
150
136
  # @example
151
- # session.validate!(client)
137
+ # session.validate!(cluster)
152
138
  #
153
- # @param [ Client ] client The client the session is attempted to be used with.
139
+ # @param [ Cluster ] cluster The cluster the session is attempted to be used with.
154
140
  #
155
141
  # @return [ nil ] nil if the session is valid.
156
142
  #
157
143
  # @raise [ Mongo::Error::InvalidSession ] Raise error if the session is not valid.
158
144
  #
159
145
  # @since 2.5.0
160
- def validate!(client)
161
- check_matching_client!(client)
146
+ def validate!(cluster)
147
+ check_matching_cluster!(cluster)
162
148
  check_if_ended!
149
+ self
163
150
  end
164
151
 
165
152
  # Process a response from the server that used this session.
@@ -173,7 +160,7 @@ module Mongo
173
160
  #
174
161
  # @since 2.5.0
175
162
  def process(result)
176
- unless implicit_session?
163
+ unless implicit?
177
164
  set_operation_time(result)
178
165
  set_cluster_time(result)
179
166
  end
@@ -229,7 +216,7 @@ module Mongo
229
216
  #
230
217
  # @since 2.5.0
231
218
  def retry_writes?
232
- !!client.options[:retry_writes] && (cluster.replica_set? || cluster.sharded?)
219
+ !!cluster.options[:retry_writes] && (cluster.replica_set? || cluster.sharded?)
233
220
  end
234
221
 
235
222
  # Get the session id.
@@ -247,7 +234,7 @@ module Mongo
247
234
  # Increment and return the next transaction number.
248
235
  #
249
236
  # @example Get the next transaction number.
250
- # server_session.next_txn_num
237
+ # session.next_txn_num
251
238
  #
252
239
  # @return [ Integer ] The next transaction number.
253
240
  #
@@ -256,6 +243,18 @@ module Mongo
256
243
  @server_session.next_txn_num if @server_session
257
244
  end
258
245
 
246
+ # Is this session an implicit one (not user-created).
247
+ #
248
+ # @example Is the session implicit?
249
+ # session.implicit?
250
+ #
251
+ # @return [ true, false ] Whether this session is implicit.
252
+ #
253
+ # @since 2.5.1
254
+ def implicit?
255
+ @implicit_session ||= !!(@options.key?(:implicit) && @options[:implicit] == true)
256
+ end
257
+
259
258
  private
260
259
 
261
260
  def causal_consistency_doc(read_concern)
@@ -274,10 +273,6 @@ module Mongo
274
273
  end)
275
274
  end
276
275
 
277
- def implicit_session?
278
- @implicit_session ||= !!(@options.key?(:implicit) && @options[:implicit] == true)
279
- end
280
-
281
276
  def set_operation_time(result)
282
277
  if result && result.operation_time
283
278
  @operation_time = result.operation_time
@@ -298,8 +293,8 @@ module Mongo
298
293
  raise Mongo::Error::InvalidSession.new(SESSION_ENDED_ERROR_MSG) if ended?
299
294
  end
300
295
 
301
- def check_matching_client!(client)
302
- if @client != client
296
+ def check_matching_cluster!(cluster)
297
+ if @cluster != cluster
303
298
  raise Mongo::Error::InvalidSession.new(MISMATCHED_CLUSTER_ERROR_MSG)
304
299
  end
305
300
  end