mongo 2.5.0 → 2.5.1

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