mongo 2.5.0.beta → 2.5.0

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 (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