mongo 2.5.0.beta → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo/address.rb +1 -1
  5. data/lib/mongo/address/unix.rb +1 -1
  6. data/lib/mongo/auth/user.rb +0 -5
  7. data/lib/mongo/auth/user/view.rb +4 -4
  8. data/lib/mongo/bulk_write.rb +60 -32
  9. data/lib/mongo/client.rb +44 -8
  10. data/lib/mongo/cluster.rb +14 -12
  11. data/lib/mongo/cluster/periodic_executor.rb +106 -0
  12. data/lib/mongo/cluster/{cursor_reaper.rb → reapers/cursor_reaper.rb} +5 -37
  13. data/lib/mongo/cluster/reapers/socket_reaper.rb +59 -0
  14. data/lib/mongo/collection.rb +9 -6
  15. data/lib/mongo/collection/view.rb +2 -2
  16. data/lib/mongo/collection/view/builder/aggregation.rb +2 -1
  17. data/lib/mongo/collection/view/builder/find_command.rb +1 -1
  18. data/lib/mongo/collection/view/change_stream.rb +14 -1
  19. data/lib/mongo/collection/view/map_reduce.rb +30 -13
  20. data/lib/mongo/collection/view/readable.rb +5 -5
  21. data/lib/mongo/collection/view/writable.rb +98 -51
  22. data/lib/mongo/error.rb +3 -0
  23. data/lib/mongo/error/invalid_txt_record.rb +27 -0
  24. data/lib/mongo/error/invalid_uri.rb +7 -6
  25. data/lib/mongo/error/mismatched_domain.rb +27 -0
  26. data/lib/mongo/error/no_srv_records.rb +26 -0
  27. data/lib/mongo/error/unsupported_features.rb +0 -18
  28. data/lib/mongo/index/view.rb +2 -2
  29. data/lib/mongo/operation.rb +1 -0
  30. data/lib/mongo/operation/causally_consistent.rb +33 -0
  31. data/lib/mongo/operation/commands.rb +2 -1
  32. data/lib/mongo/operation/commands/aggregate.rb +2 -7
  33. data/lib/mongo/operation/commands/count.rb +27 -0
  34. data/lib/mongo/operation/commands/distinct.rb +27 -0
  35. data/lib/mongo/operation/commands/find.rb +3 -1
  36. data/lib/mongo/operation/commands/map_reduce.rb +1 -0
  37. data/lib/mongo/operation/commands/parallel_scan.rb +1 -0
  38. data/lib/mongo/operation/specifiable.rb +12 -0
  39. data/lib/mongo/operation/uses_command_op_msg.rb +36 -5
  40. data/lib/mongo/operation/write.rb +0 -5
  41. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -8
  42. data/lib/mongo/operation/write/bulk/mergable.rb +2 -0
  43. data/lib/mongo/operation/write/command/create_index.rb +19 -0
  44. data/lib/mongo/operation/write/command/create_user.rb +19 -0
  45. data/lib/mongo/operation/write/command/delete.rb +1 -2
  46. data/lib/mongo/operation/write/command/drop_index.rb +19 -0
  47. data/lib/mongo/operation/write/command/insert.rb +1 -2
  48. data/lib/mongo/operation/write/command/remove_user.rb +19 -0
  49. data/lib/mongo/operation/write/command/update.rb +1 -2
  50. data/lib/mongo/operation/write/command/update_user.rb +19 -0
  51. data/lib/mongo/operation/write/write_command_enabled.rb +1 -3
  52. data/lib/mongo/protocol/compressed.rb +2 -1
  53. data/lib/mongo/protocol/serializers.rb +6 -6
  54. data/lib/mongo/retryable.rb +48 -5
  55. data/lib/mongo/server.rb +15 -0
  56. data/lib/mongo/server/connection.rb +21 -1
  57. data/lib/mongo/server/connection_pool.rb +3 -0
  58. data/lib/mongo/server/connection_pool/queue.rb +50 -5
  59. data/lib/mongo/server/description.rb +11 -3
  60. data/lib/mongo/server/description/features.rb +26 -7
  61. data/lib/mongo/session.rb +133 -6
  62. data/lib/mongo/session/server_session.rb +30 -0
  63. data/lib/mongo/session/session_pool.rb +20 -20
  64. data/lib/mongo/uri.rb +88 -44
  65. data/lib/mongo/uri/srv_protocol.rb +158 -0
  66. data/lib/mongo/version.rb +1 -1
  67. data/lib/mongo/write_concern/normalizable.rb +12 -0
  68. data/mongo.gemspec +1 -2
  69. data/spec/mongo/address_spec.rb +12 -0
  70. data/spec/mongo/auth/user/view_spec.rb +1 -5
  71. data/spec/mongo/bulk_write_spec.rb +232 -401
  72. data/spec/mongo/change_stream_examples_spec.rb +150 -0
  73. data/spec/mongo/client_spec.rb +142 -2
  74. data/spec/mongo/cluster/cursor_reaper_spec.rb +0 -70
  75. data/spec/mongo/cluster/socket_reaper_spec.rb +32 -0
  76. data/spec/mongo/cluster_spec.rb +11 -7
  77. data/spec/mongo/collection/view/aggregation_spec.rb +46 -1
  78. data/spec/mongo/collection/view/builder/find_command_spec.rb +15 -0
  79. data/spec/mongo/collection/view/change_stream_spec.rb +79 -12
  80. data/spec/mongo/collection/view/map_reduce_spec.rb +120 -4
  81. data/spec/mongo/collection/view/readable_spec.rb +23 -5
  82. data/spec/mongo/collection_spec.rb +292 -102
  83. data/spec/mongo/command_monitoring_spec.rb +26 -32
  84. data/spec/mongo/crud_spec.rb +1 -1
  85. data/spec/mongo/cursor_spec.rb +2 -3
  86. data/spec/mongo/database_spec.rb +30 -14
  87. data/spec/mongo/dns_seedlist_discovery_spec.rb +94 -0
  88. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  89. data/spec/mongo/grid/stream/write_spec.rb +1 -1
  90. data/spec/mongo/index/view_spec.rb +8 -46
  91. data/spec/mongo/operation/write/bulk/delete_spec.rb +2 -2
  92. data/spec/mongo/operation/write/bulk/insert_spec.rb +2 -10
  93. data/spec/mongo/operation/write/{create_index_spec.rb → command/create_index_spec.rb} +2 -6
  94. data/spec/mongo/operation/write/command/delete_spec.rb +35 -7
  95. data/spec/mongo/operation/write/{drop_index_spec.rb → command/drop_index_spec.rb} +1 -1
  96. data/spec/mongo/operation/write/command/insert_spec.rb +37 -6
  97. data/spec/mongo/operation/write/{remove_user_spec.rb → command/remove_user_spec.rb} +2 -6
  98. data/spec/mongo/operation/write/command/update_spec.rb +34 -7
  99. data/spec/mongo/operation/write/{update_user_spec.rb → command/update_user_spec.rb} +1 -1
  100. data/spec/mongo/operation/write/create_user_spec.rb +1 -1
  101. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  102. data/spec/mongo/operation/write/insert_spec.rb +2 -10
  103. data/spec/mongo/operation/write/update_spec.rb +3 -15
  104. data/spec/mongo/retryable_spec.rb +1 -1
  105. data/spec/mongo/retryable_writes_spec.rb +815 -0
  106. data/spec/mongo/server/connection_pool/queue_spec.rb +35 -2
  107. data/spec/mongo/server/connection_pool_spec.rb +234 -1
  108. data/spec/mongo/server/connection_spec.rb +10 -6
  109. data/spec/mongo/server/description/features_spec.rb +51 -37
  110. data/spec/mongo/server/description_spec.rb +6 -3
  111. data/spec/mongo/server_spec.rb +87 -0
  112. data/spec/mongo/session/server_session_spec.rb +43 -0
  113. data/spec/mongo/session/session_pool_spec.rb +63 -27
  114. data/spec/mongo/session_spec.rb +247 -0
  115. data/spec/mongo/shell_examples_spec.rb +2 -2
  116. data/spec/mongo/uri/srv_protocol_spec.rb +933 -0
  117. data/spec/mongo/uri_spec.rb +42 -3
  118. data/spec/mongo/write_concern/acknowledged_spec.rb +11 -0
  119. data/spec/mongo/write_concern/unacknowledged_spec.rb +11 -0
  120. data/spec/spec_helper.rb +11 -25
  121. data/spec/support/authorization.rb +2 -1
  122. data/spec/support/connection_string.rb +8 -4
  123. data/spec/support/crud.rb +38 -24
  124. data/spec/support/crud/write.rb +30 -3
  125. data/spec/support/crud_tests/read/aggregate-out.yml +21 -0
  126. data/spec/support/crud_tests/write/bulkWrite-arrayFilters.yml +44 -0
  127. data/spec/support/crud_tests/write/findOneAndUpdate-arrayFilters.yml +1 -1
  128. data/spec/support/crud_tests/write/insertMany.yml +1 -3
  129. data/spec/support/crud_tests/write/replaceOne.yml +1 -1
  130. data/spec/support/crud_tests/write/updateMany-arrayFilters.yml +1 -1
  131. data/spec/support/crud_tests/write/updateOne-arrayFilters.yml +1 -1
  132. data/spec/support/dns_seedlist_discovery_tests/longer-parent-in-return.yml +11 -0
  133. data/spec/support/dns_seedlist_discovery_tests/misformatted-option.yml +5 -0
  134. data/spec/support/dns_seedlist_discovery_tests/no-results.yml +5 -0
  135. data/spec/support/dns_seedlist_discovery_tests/not-enough-parts.yml +5 -0
  136. data/spec/support/dns_seedlist_discovery_tests/one-result-default-port.yml +10 -0
  137. data/spec/support/dns_seedlist_discovery_tests/one-txt-record-multiple-strings.yml +10 -0
  138. data/spec/support/dns_seedlist_discovery_tests/one-txt-record.yml +11 -0
  139. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch1.yml +5 -0
  140. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch2.yml +5 -0
  141. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch3.yml +5 -0
  142. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch4.yml +5 -0
  143. data/spec/support/dns_seedlist_discovery_tests/parent-part-mismatch5.yml +5 -0
  144. data/spec/support/dns_seedlist_discovery_tests/returned-parent-too-short.yml +5 -0
  145. data/spec/support/dns_seedlist_discovery_tests/returned-parent-wrong.yml +5 -0
  146. data/spec/support/dns_seedlist_discovery_tests/two-results-default-port.yml +11 -0
  147. data/spec/support/dns_seedlist_discovery_tests/two-results-nonstandard-port.yml +11 -0
  148. data/spec/support/dns_seedlist_discovery_tests/two-txt-records.yml +5 -0
  149. data/spec/support/dns_seedlist_discovery_tests/txt-record-not-allowed-option.yml +5 -0
  150. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-ssl-option.yml +11 -0
  151. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-overridden-uri-option.yml +11 -0
  152. data/spec/support/dns_seedlist_discovery_tests/txt-record-with-unallowed-option.yml +5 -0
  153. data/spec/support/dns_seedlist_discovery_tests/uri-with-port.yml +5 -0
  154. data/spec/support/dns_seedlist_discovery_tests/uri-with-two-hosts.yml +5 -0
  155. data/spec/support/retryable_writes_tests/bulkWrite.yml +305 -0
  156. data/spec/support/retryable_writes_tests/deleteOne.yml +51 -0
  157. data/spec/support/retryable_writes_tests/findOneAndDelete.yml +52 -0
  158. data/spec/support/retryable_writes_tests/findOneAndReplace.yml +57 -0
  159. data/spec/support/retryable_writes_tests/findOneAndUpdate.yml +56 -0
  160. data/spec/support/retryable_writes_tests/insertMany.yml +72 -0
  161. data/spec/support/retryable_writes_tests/insertOne.yml +55 -0
  162. data/spec/support/retryable_writes_tests/replaceOne.yml +60 -0
  163. data/spec/support/retryable_writes_tests/updateOne.yml +120 -0
  164. data/spec/support/shared/session.rb +525 -24
  165. metadata +437 -350
  166. metadata.gz.sig +0 -0
  167. data/lib/mongo/operation/commands/user_query.rb +0 -72
  168. data/lib/mongo/operation/write/create_index.rb +0 -67
  169. data/lib/mongo/operation/write/create_user.rb +0 -50
  170. data/lib/mongo/operation/write/drop_index.rb +0 -63
  171. data/lib/mongo/operation/write/remove_user.rb +0 -48
  172. data/lib/mongo/operation/write/update_user.rb +0 -50
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'change streams examples in Ruby', if: test_change_streams? do
4
+
5
+ let!(:inventory) do
6
+ client[:inventory]
7
+ end
8
+
9
+ let(:client) do
10
+ authorized_client.with(max_pool_size: 5, wait_queue_timeout: 3)
11
+ end
12
+
13
+ before do
14
+ inventory.drop
15
+ end
16
+
17
+ after do
18
+ client.close
19
+ inventory.drop
20
+ end
21
+
22
+ context 'example 1 - basic watching'do
23
+
24
+ it 'returns a change after an insertion' do
25
+
26
+ insert_thread = Thread.new do
27
+ sleep 2
28
+ inventory.insert_one(x: 1)
29
+ end
30
+
31
+ stream_thread = Thread.new do
32
+
33
+ # Start Changestream Example 1
34
+
35
+ cursor = inventory.watch.to_enum
36
+ next_change = cursor.next
37
+
38
+ # End Changestream Example 1
39
+ end
40
+
41
+ insert_thread.value
42
+ change = stream_thread.value
43
+
44
+ expect(change['_id']).not_to be_nil
45
+ expect(change['_id']['_data']).not_to be_nil
46
+ expect(change['operationType']).to eq('insert')
47
+ expect(change['fullDocument']).not_to be_nil
48
+ expect(change['fullDocument']['_id']).not_to be_nil
49
+ expect(change['fullDocument']['x']).to eq(1)
50
+ expect(change['ns']).not_to be_nil
51
+ expect(change['ns']['db']).to eq(TEST_DB)
52
+ expect(change['ns']['coll']).to eq(inventory.name)
53
+ expect(change['documentKey']).not_to be_nil
54
+ expect(change['documentKey']['_id']).to eq(change['fullDocument']['_id'])
55
+ end
56
+ end
57
+
58
+ context 'example 2 - full document update lookup specified' do
59
+
60
+ it 'returns a change and the delta after an insertion' do
61
+
62
+ inventory.insert_one(_id: 1, x: 2)
63
+
64
+ update_thread = Thread.new do
65
+ sleep 2
66
+ inventory.update_one({ _id: 1}, { '$set' => { x: 5 }})
67
+ end
68
+
69
+ stream_thread = Thread.new do
70
+
71
+ # Start Changestream Example 2
72
+
73
+ cursor = inventory.watch([], full_document: 'updateLookup').to_enum
74
+ next_change = cursor.next
75
+
76
+ # End Changestream Example 2
77
+ end
78
+
79
+
80
+ update_thread.value
81
+ change = stream_thread.value
82
+
83
+ expect(change['_id']).not_to be_nil
84
+ expect(change['_id']['_data']).not_to be_nil
85
+ expect(change['operationType']).to eq('update')
86
+ expect(change['fullDocument']).not_to be_nil
87
+ expect(change['fullDocument']['_id']).to eq(1)
88
+ expect(change['fullDocument']['x']).to eq(5)
89
+ expect(change['ns']).not_to be_nil
90
+ expect(change['ns']['db']).to eq(TEST_DB)
91
+ expect(change['ns']['coll']).to eq(inventory.name)
92
+ expect(change['documentKey']).not_to be_nil
93
+ expect(change['documentKey']['_id']).to eq(1)
94
+ expect(change['updateDescription']).not_to be_nil
95
+ expect(change['updateDescription']['updatedFields']).not_to be_nil
96
+ expect(change['updateDescription']['updatedFields']['x']).to eq(5)
97
+ expect(change['updateDescription']['removedFields']).to eq([])
98
+ end
99
+ end
100
+
101
+ context 'example 3 - resuming from a previous change' do
102
+
103
+ it 'returns the correct change when resuming' do
104
+
105
+ stream = inventory.watch
106
+ cursor = stream.to_enum
107
+ inventory.insert_one(x: 1)
108
+ next_change = cursor.next
109
+
110
+ expect(next_change['_id']).not_to be_nil
111
+ expect(next_change['_id']['_data']).not_to be_nil
112
+ expect(next_change['operationType']).to eq('insert')
113
+ expect(next_change['fullDocument']).not_to be_nil
114
+ expect(next_change['fullDocument']['_id']).not_to be_nil
115
+ expect(next_change['fullDocument']['x']).to eq(1)
116
+ expect(next_change['ns']).not_to be_nil
117
+ expect(next_change['ns']['db']).to eq(TEST_DB)
118
+ expect(next_change['ns']['coll']).to eq(inventory.name)
119
+ expect(next_change['documentKey']).not_to be_nil
120
+ expect(next_change['documentKey']['_id']).to eq(next_change['fullDocument']['_id'])
121
+
122
+ inventory.insert_one(x: 2)
123
+ next_next_change = cursor.next
124
+ stream.close
125
+
126
+ expect(next_next_change['_id']).not_to be_nil
127
+ expect(next_next_change['_id']['_data']).not_to be_nil
128
+ expect(next_next_change['operationType']).to eq('insert')
129
+ expect(next_next_change['fullDocument']).not_to be_nil
130
+ expect(next_next_change['fullDocument']['_id']).not_to be_nil
131
+ expect(next_next_change['fullDocument']['x']).to eq(2)
132
+ expect(next_next_change['ns']).not_to be_nil
133
+ expect(next_next_change['ns']['db']).to eq(TEST_DB)
134
+ expect(next_next_change['ns']['coll']).to eq(inventory.name)
135
+ expect(next_next_change['documentKey']).not_to be_nil
136
+ expect(next_next_change['documentKey']['_id']).to eq(next_next_change['fullDocument']['_id'])
137
+
138
+ # Start Changestream Example 3
139
+
140
+ resume_token = next_change['_id']
141
+ cursor = inventory.watch([], resume_after: resume_token).to_enum
142
+ resumed_change = cursor.next
143
+
144
+ # End Changestream Example 3
145
+
146
+ expect(resumed_change.length).to eq(next_next_change.length)
147
+ resumed_change.each { |key| expect(resumed_change[key]).to eq(next_next_change[key]) }
148
+ end
149
+ end
150
+ end
@@ -218,6 +218,21 @@ describe Mongo::Client do
218
218
 
219
219
  context 'when providing options' do
220
220
 
221
+ context 'when retry_writes is defined' do
222
+
223
+ let(:options) do
224
+ { retry_writes: true }
225
+ end
226
+
227
+ let(:client) do
228
+ described_class.new([default_address.seed], authorized_client.options.merge(options))
229
+ end
230
+
231
+ it 'sets the option' do
232
+ expect(client.options['retry_writes']).to eq(options[:retry_writes])
233
+ end
234
+ end
235
+
221
236
  context 'when compressors are provided' do
222
237
 
223
238
  let(:client) do
@@ -617,6 +632,21 @@ describe Mongo::Client do
617
632
 
618
633
  context 'when providing a connection string' do
619
634
 
635
+ context 'when the string uses the SRV Protocol' do
636
+
637
+ let!(:uri) do
638
+ 'mongodb+srv://test5.test.build.10gen.cc/testdb'
639
+ end
640
+
641
+ let(:client) do
642
+ described_class.new(uri)
643
+ end
644
+
645
+ it 'sets the database' do
646
+ expect(client.options[:database]).to eq('testdb')
647
+ end
648
+ end
649
+
620
650
  context 'when a database is provided' do
621
651
 
622
652
  let!(:uri) do
@@ -1276,6 +1306,22 @@ describe Mongo::Client do
1276
1306
  'admin'
1277
1307
  )
1278
1308
  end
1309
+
1310
+ context 'when filter criteria is present', if: sessions_enabled? do
1311
+
1312
+ let(:result) do
1313
+ root_authorized_client.database_names(filter)
1314
+ end
1315
+
1316
+ let(:filter) do
1317
+ { name: TEST_DB }
1318
+ end
1319
+
1320
+ it 'returns a filtered list of database names' do
1321
+ expect(result.length).to eq(1)
1322
+ expect(result.first).to eq(filter[:name])
1323
+ end
1324
+ end
1279
1325
  end
1280
1326
 
1281
1327
  describe '#list_databases' do
@@ -1286,9 +1332,94 @@ describe Mongo::Client do
1286
1332
  i['name']
1287
1333
  end).to include('admin')
1288
1334
  end
1335
+
1336
+ context 'when filter criteria is present', if: sessions_enabled? do
1337
+
1338
+ let(:result) do
1339
+ root_authorized_client.list_databases(filter)
1340
+ end
1341
+
1342
+ let(:filter) do
1343
+ { name: TEST_DB }
1344
+ end
1345
+
1346
+ it 'returns a filtered list of database info documents' do
1347
+ expect(result.length).to eq(1)
1348
+ expect(result[0]['name']).to eq(filter[:name])
1349
+ end
1350
+ end
1351
+
1352
+ context 'when name_only is true' do
1353
+
1354
+ let(:client_options) do
1355
+ root_authorized_client.options.merge(heartbeat_frequency: 100, monitoring: true)
1356
+ end
1357
+
1358
+ let(:client) do
1359
+ # Monitoring subscribers won't be set up when using Client#with, so a new client must be created.
1360
+ Mongo::Client.new(ADDRESSES, client_options).tap do |cl|
1361
+ cl.subscribe(Mongo::Monitoring::COMMAND, subscriber)
1362
+ end
1363
+ end
1364
+
1365
+ let(:subscriber) do
1366
+ EventSubscriber.new
1367
+ end
1368
+
1369
+ let(:command) do
1370
+ subscriber.started_events.find { |c| c.command_name == :listDatabases }.command
1371
+ end
1372
+
1373
+ before do
1374
+ client.list_databases({}, true)
1375
+ end
1376
+
1377
+ it 'sends the command with the nameOnly flag set to true' do
1378
+ expect(command[:nameOnly]).to be(true)
1379
+ end
1380
+ end
1381
+ end
1382
+
1383
+ describe '#list_mongo_databases' do
1384
+
1385
+ let(:options) do
1386
+ { read: { mode: :secondary } }
1387
+ end
1388
+
1389
+ let(:client) do
1390
+ root_authorized_client.with(options)
1391
+ end
1392
+
1393
+ let(:result) do
1394
+ client.list_mongo_databases
1395
+ end
1396
+
1397
+ it 'returns a list of Mongo::Database objects' do
1398
+ expect(result).to all(be_a(Mongo::Database))
1399
+ end
1400
+
1401
+ it 'creates database with specified options' do
1402
+ expect(result.first.options[:read]).to eq(BSON::Document.new(options)[:read])
1403
+ end
1404
+
1405
+ context 'when filter criteria is present', if: sessions_enabled? do
1406
+
1407
+ let(:result) do
1408
+ client.list_mongo_databases(filter)
1409
+ end
1410
+
1411
+ let(:filter) do
1412
+ { name: TEST_DB }
1413
+ end
1414
+
1415
+ it 'returns a filtered list of Mongo::Database objects' do
1416
+ expect(result.length).to eq(1)
1417
+ expect(result.first.name).to eq(filter[:name])
1418
+ end
1419
+ end
1289
1420
  end
1290
1421
 
1291
- describe '#close' do
1422
+ describe '#close' do
1292
1423
 
1293
1424
  let(:client) do
1294
1425
  described_class.new(['127.0.0.1:27017'])
@@ -1359,7 +1490,7 @@ describe Mongo::Client do
1359
1490
  authorized_client.start_session
1360
1491
  end
1361
1492
 
1362
- context 'when sessions are supported', if: sessions_enabled? do
1493
+ context 'when sessions are supported', if: test_sessions? do
1363
1494
 
1364
1495
  it 'creates a session' do
1365
1496
  expect(session).to be_a(Mongo::Session)
@@ -1410,6 +1541,10 @@ describe Mongo::Client do
1410
1541
  end
1411
1542
 
1412
1543
  before do
1544
+ session_a_server_session.next_txn_num
1545
+ session_a_server_session.next_txn_num
1546
+ session_b_server_session.next_txn_num
1547
+ session_b_server_session.next_txn_num
1413
1548
  session_a.end_session
1414
1549
  session_b.end_session
1415
1550
  end
@@ -1418,6 +1553,11 @@ describe Mongo::Client do
1418
1553
  expect(authorized_client.start_session.instance_variable_get(:@server_session)).to be(session_b_server_session)
1419
1554
  expect(authorized_client.start_session.instance_variable_get(:@server_session)).to be(session_a_server_session)
1420
1555
  end
1556
+
1557
+ it 'preserves the transaction numbers on the server sessions' do
1558
+ expect(authorized_client.start_session.next_txn_num).to be(2)
1559
+ expect(authorized_client.start_session.next_txn_num).to be(2)
1560
+ end
1421
1561
  end
1422
1562
 
1423
1563
  context 'when an implicit session is used' do
@@ -25,47 +25,6 @@ describe Mongo::Cluster::CursorReaper do
25
25
  end
26
26
  end
27
27
 
28
- describe '#run' do
29
-
30
- it 'starts a thread calling #kill_cursors' do
31
- reaper.run!
32
- expect(reaper.instance_variable_get(:@thread)).to be_a(Thread)
33
- end
34
-
35
- context 'when run is called more than once' do
36
-
37
- let!(:reaper_thread) do
38
- reaper.run!
39
- reaper.instance_variable_get(:@reaper)
40
- end
41
-
42
- it 'only starts a thread once' do
43
- reaper.run!
44
- expect(reaper.instance_variable_get(:@reaper)).to be(reaper_thread)
45
- end
46
- end
47
-
48
- context 'when there are ops in the list to execute' do
49
-
50
- let(:server) { double('server') }
51
- let(:cursor_id) { 1 }
52
- let(:op_spec_1) { double('op_spec_1') }
53
- let(:op_spec_2) { double('op_spec_2') }
54
- let(:to_kill) { reaper.instance_variable_get(:@to_kill)}
55
-
56
- before do
57
- reaper.register_cursor(cursor_id)
58
- reaper.schedule_kill_cursor(cursor_id, op_spec_1, server)
59
- reaper.run!
60
- sleep(Mongo::Cluster::CursorReaper::FREQUENCY + 1)
61
- end
62
-
63
- it 'executes the ops in the thread' do
64
- expect(reaper.instance_variable_get(:@to_kill).size).to eq(0)
65
- end
66
- end
67
- end
68
-
69
28
  describe '#schedule_kill_cursor' do
70
29
 
71
30
  let(:server) { double('server') }
@@ -184,33 +143,4 @@ describe Mongo::Cluster::CursorReaper do
184
143
  end
185
144
  end
186
145
  end
187
-
188
- describe '#stop!' do
189
-
190
- let(:thread) do
191
- reaper.run!
192
- reaper.stop!
193
- sleep(0.5)
194
- reaper.instance_variable_get(:@thread)
195
- end
196
-
197
- it 'stops the thread from running' do
198
- expect(thread.alive?).to be(false)
199
- end
200
- end
201
-
202
- describe '#restart!' do
203
-
204
- let(:thread) do
205
- reaper.run!
206
- reaper.stop!
207
- sleep(0.5)
208
- reaper.restart!
209
- reaper.instance_variable_get(:@thread)
210
- end
211
-
212
- it 'restarts the thread' do
213
- expect(thread.alive?).to be(true)
214
- end
215
- end
216
146
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Cluster::SocketReaper do
4
+
5
+ let(:cluster) do
6
+ authorized_client.cluster
7
+ end
8
+
9
+ let(:reaper) do
10
+ described_class.new(cluster)
11
+ end
12
+
13
+ describe '#initialize' do
14
+
15
+ it 'takes a cluster as an argument' do
16
+ expect(reaper).to be_a(described_class)
17
+ end
18
+ end
19
+
20
+ describe '#execute' do
21
+
22
+ before do
23
+ cluster.servers.each do |s|
24
+ expect(s.pool).to receive(:close_stale_sockets!).and_call_original
25
+ end
26
+ end
27
+
28
+ it 'calls close_stale_sockets on each connection pool in the cluster' do
29
+ reaper.execute
30
+ end
31
+ end
32
+ end