mongo 2.9.2 → 2.10.0.rc0

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 (227) 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.rb +1 -0
  5. data/lib/mongo/auth/user/view.rb +4 -4
  6. data/lib/mongo/bulk_write.rb +14 -8
  7. data/lib/mongo/bulk_write/result.rb +1 -1
  8. data/lib/mongo/bulk_write/result_combiner.rb +2 -2
  9. data/lib/mongo/bulk_write/transformable.rb +17 -9
  10. data/lib/mongo/client.rb +107 -16
  11. data/lib/mongo/cluster.rb +47 -25
  12. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  13. data/lib/mongo/cluster_time.rb +139 -0
  14. data/lib/mongo/collection.rb +84 -25
  15. data/lib/mongo/collection/view.rb +7 -3
  16. data/lib/mongo/collection/view/aggregation.rb +4 -4
  17. data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
  18. data/lib/mongo/collection/view/builder/find_command.rb +4 -1
  19. data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
  20. data/lib/mongo/collection/view/change_stream.rb +54 -66
  21. data/lib/mongo/collection/view/iterable.rb +2 -2
  22. data/lib/mongo/collection/view/map_reduce.rb +6 -4
  23. data/lib/mongo/collection/view/readable.rb +36 -16
  24. data/lib/mongo/collection/view/writable.rb +68 -22
  25. data/lib/mongo/cursor.rb +87 -20
  26. data/lib/mongo/database.rb +47 -43
  27. data/lib/mongo/database/view.rb +54 -11
  28. data/lib/mongo/error.rb +13 -4
  29. data/lib/mongo/error/invalid_write_concern.rb +2 -2
  30. data/lib/mongo/error/operation_failure.rb +65 -11
  31. data/lib/mongo/error/parser.rb +41 -8
  32. data/lib/mongo/grid/fs_bucket.rb +26 -6
  33. data/lib/mongo/grid/stream/read.rb +9 -2
  34. data/lib/mongo/grid/stream/write.rb +21 -5
  35. data/lib/mongo/index/view.rb +3 -3
  36. data/lib/mongo/lint.rb +10 -3
  37. data/lib/mongo/operation.rb +2 -0
  38. data/lib/mongo/operation/aggregate/result.rb +19 -6
  39. data/lib/mongo/operation/collections_info.rb +1 -1
  40. data/lib/mongo/operation/get_more/result.rb +9 -0
  41. data/lib/mongo/operation/list_collections/command.rb +1 -3
  42. data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
  43. data/lib/mongo/operation/parallel_scan/command.rb +4 -1
  44. data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
  45. data/lib/mongo/operation/result.rb +27 -4
  46. data/lib/mongo/operation/shared/executable.rb +19 -5
  47. data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
  48. data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
  49. data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
  50. data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
  51. data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
  52. data/lib/mongo/operation/shared/specifiable.rb +40 -0
  53. data/lib/mongo/operation/shared/unpinnable.rb +39 -0
  54. data/lib/mongo/operation/shared/write.rb +1 -1
  55. data/lib/mongo/protocol/update.rb +6 -2
  56. data/lib/mongo/retryable.rb +79 -39
  57. data/lib/mongo/server/connection.rb +10 -3
  58. data/lib/mongo/server/description.rb +25 -1
  59. data/lib/mongo/server/monitor/connection.rb +1 -1
  60. data/lib/mongo/server_selector.rb +10 -0
  61. data/lib/mongo/server_selector/selectable.rb +172 -32
  62. data/lib/mongo/session.rb +654 -581
  63. data/lib/mongo/session/session_pool.rb +1 -1
  64. data/lib/mongo/socket.rb +7 -28
  65. data/lib/mongo/socket/ssl.rb +26 -1
  66. data/lib/mongo/socket/tcp.rb +3 -0
  67. data/lib/mongo/socket/unix.rb +3 -0
  68. data/lib/mongo/uri.rb +112 -265
  69. data/lib/mongo/uri/srv_protocol.rb +4 -1
  70. data/lib/mongo/version.rb +1 -1
  71. data/lib/mongo/write_concern.rb +10 -29
  72. data/lib/mongo/write_concern/acknowledged.rb +12 -0
  73. data/lib/mongo/write_concern/base.rb +17 -13
  74. data/lib/mongo/write_concern/unacknowledged.rb +12 -0
  75. data/spec/atlas/atlas_connectivity_spec.rb +7 -37
  76. data/spec/atlas/operations_spec.rb +25 -0
  77. data/spec/integration/change_stream_examples_spec.rb +45 -31
  78. data/spec/integration/change_stream_spec.rb +305 -5
  79. data/spec/integration/client_spec.rb +44 -0
  80. data/spec/integration/command_monitoring_spec.rb +1 -0
  81. data/spec/integration/command_spec.rb +7 -1
  82. data/spec/integration/mmapv1_spec.rb +28 -0
  83. data/spec/integration/mongos_pinning_spec.rb +34 -0
  84. data/spec/integration/operation_failure_code_spec.rb +2 -2
  85. data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
  86. data/spec/integration/read_preference_spec.rb +485 -0
  87. data/spec/integration/retryable_writes_spec.rb +8 -19
  88. data/spec/integration/sdam_error_handling_spec.rb +1 -1
  89. data/spec/integration/sdam_events_spec.rb +2 -2
  90. data/spec/integration/server_description_spec.rb +14 -17
  91. data/spec/integration/server_selector_spec.rb +7 -3
  92. data/spec/integration/server_spec.rb +48 -0
  93. data/spec/integration/ssl_uri_options_spec.rb +1 -1
  94. data/spec/integration/step_down_spec.rb +10 -4
  95. data/spec/integration/transactions_examples_spec.rb +11 -10
  96. data/spec/lite_spec_helper.rb +19 -16
  97. data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
  98. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
  99. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
  100. data/spec/mongo/bulk_write_spec.rb +12 -2
  101. data/spec/mongo/client_construction_spec.rb +160 -8
  102. data/spec/mongo/client_spec.rb +5 -4
  103. data/spec/mongo/cluster_spec.rb +6 -6
  104. data/spec/mongo/cluster_time_spec.rb +148 -0
  105. data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
  106. data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
  107. data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
  108. data/spec/mongo/collection/view/readable_spec.rb +4 -4
  109. data/spec/mongo/collection_spec.rb +331 -14
  110. data/spec/mongo/cursor_spec.rb +117 -5
  111. data/spec/mongo/database_spec.rb +240 -8
  112. data/spec/mongo/error/operation_failure_spec.rb +47 -1
  113. data/spec/mongo/error/parser_spec.rb +160 -23
  114. data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
  115. data/spec/mongo/operation/result_spec.rb +27 -0
  116. data/spec/mongo/operation/update/bulk_spec.rb +1 -0
  117. data/spec/mongo/retryable_spec.rb +2 -0
  118. data/spec/mongo/server/app_metadata_spec.rb +2 -2
  119. data/spec/mongo/server/connection_spec.rb +13 -17
  120. data/spec/mongo/server/monitor/connection_spec.rb +13 -10
  121. data/spec/mongo/server_selector_spec.rb +34 -2
  122. data/spec/mongo/session/session_pool_spec.rb +14 -3
  123. data/spec/mongo/session_spec.rb +3 -3
  124. data/spec/mongo/session_transaction_spec.rb +4 -3
  125. data/spec/mongo/socket/ssl_spec.rb +19 -5
  126. data/spec/mongo/socket_spec.rb +1 -62
  127. data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
  128. data/spec/mongo/uri_option_parsing_spec.rb +94 -8
  129. data/spec/mongo/uri_spec.rb +23 -10
  130. data/spec/mongo/write_concern_spec.rb +56 -3
  131. data/spec/spec_tests/change_streams_spec.rb +2 -1
  132. data/spec/spec_tests/cmap_spec.rb +1 -1
  133. data/spec/spec_tests/crud_spec.rb +12 -2
  134. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
  135. data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
  136. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
  137. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
  138. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
  139. data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
  140. data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
  141. data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
  142. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
  143. data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
  144. data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
  145. data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
  146. data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
  147. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
  148. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
  149. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
  150. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
  151. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
  152. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
  153. data/spec/spec_tests/data/transactions/abort.yml +3 -0
  154. data/spec/spec_tests/data/transactions/bulk.yml +3 -8
  155. data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
  156. data/spec/spec_tests/data/transactions/commit.yml +3 -1
  157. data/spec/spec_tests/data/transactions/count.yml +3 -0
  158. data/spec/spec_tests/data/transactions/delete.yml +3 -0
  159. data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
  160. data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
  161. data/spec/spec_tests/data/transactions/errors.yml +3 -0
  162. data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
  163. data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
  164. data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
  165. data/spec/spec_tests/data/transactions/insert.yml +3 -0
  166. data/spec/spec_tests/data/transactions/isolation.yml +3 -0
  167. data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
  168. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
  169. data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
  170. data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
  171. data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
  172. data/spec/spec_tests/data/transactions/reads.yml +3 -0
  173. data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
  174. data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
  175. data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
  176. data/spec/spec_tests/data/transactions/run-command.yml +3 -0
  177. data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
  178. data/spec/spec_tests/data/transactions/update.yml +3 -8
  179. data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
  180. data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
  181. data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
  182. data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
  183. data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
  184. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
  185. data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
  186. data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
  187. data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
  188. data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
  189. data/spec/spec_tests/retryable_reads_spec.rb +5 -2
  190. data/spec/spec_tests/retryable_writes_spec.rb +5 -2
  191. data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
  192. data/spec/spec_tests/sdam_spec.rb +2 -2
  193. data/spec/spec_tests/transactions_api_spec.rb +1 -67
  194. data/spec/spec_tests/transactions_spec.rb +2 -66
  195. data/spec/support/authorization.rb +4 -0
  196. data/spec/support/change_streams.rb +30 -10
  197. data/spec/support/change_streams/operation.rb +27 -0
  198. data/spec/support/client_registry.rb +44 -25
  199. data/spec/support/cluster_config.rb +25 -14
  200. data/spec/support/cluster_tools.rb +32 -10
  201. data/spec/support/command_monitoring.rb +1 -1
  202. data/spec/support/common_shortcuts.rb +30 -0
  203. data/spec/support/connection_string.rb +8 -3
  204. data/spec/support/constraints.rb +34 -0
  205. data/spec/support/crud.rb +31 -16
  206. data/spec/support/crud/context.rb +23 -0
  207. data/spec/support/crud/operation.rb +311 -14
  208. data/spec/support/crud/spec.rb +2 -1
  209. data/spec/support/crud/test.rb +24 -27
  210. data/spec/support/crud/test_base.rb +22 -0
  211. data/spec/support/crud/verifier.rb +15 -1
  212. data/spec/support/event_subscriber.rb +12 -0
  213. data/spec/support/sdam_formatter_integration.rb +12 -6
  214. data/spec/support/shared/server_selector.rb +10 -0
  215. data/spec/support/shared/session.rb +13 -12
  216. data/spec/support/spec_config.rb +32 -22
  217. data/spec/support/spec_setup.rb +2 -2
  218. data/spec/support/transactions.rb +87 -0
  219. data/spec/support/transactions/context.rb +33 -0
  220. data/spec/support/transactions/operation.rb +99 -349
  221. data/spec/support/transactions/spec.rb +1 -3
  222. data/spec/support/transactions/test.rb +110 -49
  223. data/spec/support/utils.rb +74 -1
  224. metadata +52 -10
  225. metadata.gz.sig +0 -0
  226. data/spec/support/crud/read.rb +0 -265
  227. data/spec/support/crud/write.rb +0 -284
@@ -0,0 +1,347 @@
1
+ runOn:
2
+ -
3
+ minServerVersion: "4.1.8"
4
+ topology: ["sharded"]
5
+
6
+ database_name: &database_name "transaction-tests"
7
+ collection_name: &collection_name "test"
8
+
9
+ data: []
10
+
11
+ tests:
12
+ - description: commitTransaction explicit retries include recoveryToken
13
+ useMultipleMongoses: true
14
+ operations:
15
+ - name: startTransaction
16
+ object: session0
17
+ - name: insertOne
18
+ object: collection
19
+ arguments:
20
+ session: session0
21
+ document:
22
+ _id: 1
23
+ result:
24
+ insertedId: 1
25
+ - name: commitTransaction
26
+ object: session0
27
+ - name: commitTransaction
28
+ object: session0
29
+ - name: commitTransaction
30
+ object: session0
31
+
32
+ expectations:
33
+ - command_started_event:
34
+ command:
35
+ insert: *collection_name
36
+ documents:
37
+ - _id: 1
38
+ ordered: true
39
+ readConcern:
40
+ lsid: session0
41
+ txnNumber:
42
+ $numberLong: "1"
43
+ startTransaction: true
44
+ autocommit: false
45
+ writeConcern:
46
+ command_name: insert
47
+ database_name: *database_name
48
+ - command_started_event:
49
+ command:
50
+ commitTransaction: 1
51
+ lsid: session0
52
+ txnNumber:
53
+ $numberLong: "1"
54
+ startTransaction:
55
+ autocommit: false
56
+ writeConcern:
57
+ recoveryToken: 42
58
+ command_name: commitTransaction
59
+ database_name: admin
60
+ - command_started_event:
61
+ command:
62
+ commitTransaction: 1
63
+ lsid: session0
64
+ txnNumber:
65
+ $numberLong: "1"
66
+ startTransaction:
67
+ autocommit: false
68
+ # commitTransaction applies w:majority on retries
69
+ writeConcern: { w: majority, wtimeout: 10000 }
70
+ recoveryToken: 42
71
+ command_name: commitTransaction
72
+ database_name: admin
73
+ - command_started_event:
74
+ command:
75
+ commitTransaction: 1
76
+ lsid: session0
77
+ txnNumber:
78
+ $numberLong: "1"
79
+ startTransaction:
80
+ autocommit: false
81
+ # commitTransaction applies w:majority on retries
82
+ writeConcern: { w: majority, wtimeout: 10000 }
83
+ recoveryToken: 42
84
+ command_name: commitTransaction
85
+ database_name: admin
86
+
87
+ outcome:
88
+ collection:
89
+ data:
90
+ - _id: 1
91
+
92
+ - description: commitTransaction retry succeeds on new mongos
93
+ useMultipleMongoses: true
94
+ operations:
95
+ - name: startTransaction
96
+ object: session0
97
+ arguments:
98
+ options:
99
+ writeConcern:
100
+ w: majority
101
+ - name: insertOne
102
+ object: collection
103
+ arguments:
104
+ session: session0
105
+ document:
106
+ _id: 1
107
+ result:
108
+ insertedId: 1
109
+ # Enable the fail point only on the Mongos that session0 is pinned to.
110
+ - name: targetedFailPoint
111
+ object: testRunner
112
+ arguments:
113
+ session: session0
114
+ failPoint:
115
+ configureFailPoint: failCommand
116
+ mode: { times: 1 }
117
+ data:
118
+ failCommands: ["commitTransaction"]
119
+ writeConcernError:
120
+ code: 91
121
+ errmsg: Replication is being shut down
122
+ # The client sees a retryable writeConcernError on the first
123
+ # commitTransaction due to the fail point but it actually succeeds on the
124
+ # server (SERVER-39346). The retry will succeed both on a new mongos and
125
+ # on the original.
126
+ - name: commitTransaction
127
+ object: session0
128
+
129
+ expectations:
130
+ - command_started_event:
131
+ command:
132
+ insert: *collection_name
133
+ documents:
134
+ - _id: 1
135
+ ordered: true
136
+ readConcern:
137
+ lsid: session0
138
+ txnNumber:
139
+ $numberLong: "1"
140
+ startTransaction: true
141
+ autocommit: false
142
+ writeConcern:
143
+ command_name: insert
144
+ database_name: *database_name
145
+ - command_started_event:
146
+ command:
147
+ commitTransaction: 1
148
+ lsid: session0
149
+ txnNumber:
150
+ $numberLong: "1"
151
+ startTransaction:
152
+ autocommit: false
153
+ writeConcern:
154
+ w: majority
155
+ recoveryToken: 42
156
+ command_name: commitTransaction
157
+ database_name: admin
158
+ - command_started_event:
159
+ command:
160
+ commitTransaction: 1
161
+ lsid: session0
162
+ txnNumber:
163
+ $numberLong: "1"
164
+ startTransaction:
165
+ autocommit: false
166
+ # commitTransaction applies w:majority on retries
167
+ writeConcern: { w: majority, wtimeout: 10000 }
168
+ recoveryToken: 42
169
+ command_name: commitTransaction
170
+ database_name: admin
171
+
172
+ outcome:
173
+ collection:
174
+ data:
175
+ - _id: 1
176
+
177
+ - description: commitTransaction retry fails on new mongos
178
+ useMultipleMongoses: true
179
+ clientOptions:
180
+ # Increase heartbeatFrequencyMS to avoid the race condition where an in
181
+ # flight heartbeat refreshes the first mongoes' SDAM state in between
182
+ # the initial commitTransaction and the retry attempt.
183
+ heartbeatFrequencyMS: 30000
184
+ operations:
185
+ - name: startTransaction
186
+ object: session0
187
+ - name: insertOne
188
+ object: collection
189
+ arguments:
190
+ session: session0
191
+ document:
192
+ _id: 1
193
+ result:
194
+ insertedId: 1
195
+ # Enable the fail point only on the Mongos that session0 is pinned to.
196
+ # Fail isMaster to prevent the heartbeat requested directly after the
197
+ # retryable commit error from racing with server selection for the retry.
198
+ # Note: times: 7 is slightly artbitrary but it accounts for one failed
199
+ # commit and some SDAM heartbeats. A test runner will have multiple
200
+ # clients connected to this server so this fail point configuration
201
+ # is also racy.
202
+ - name: targetedFailPoint
203
+ object: testRunner
204
+ arguments:
205
+ session: session0
206
+ failPoint:
207
+ configureFailPoint: failCommand
208
+ mode: { times: 7 }
209
+ data:
210
+ failCommands: ["commitTransaction", "isMaster"]
211
+ closeConnection: true
212
+ # The first commitTransaction sees a retryable connection error due to
213
+ # the fail point and also fails on the server. The retry attempt on a
214
+ # new mongos will wait for the transaction to timeout and will fail
215
+ # because the transaction was aborted. Note that the retry attempt should
216
+ # not select the original mongos because that server's SDAM state is
217
+ # reset by the connection error, heartbeatFrequencyMS is high, and
218
+ # subsequent isMaster heartbeats should fail.
219
+ - name: commitTransaction
220
+ object: session0
221
+ result:
222
+ # https://jira.mongodb.org/browse/SPEC-1330
223
+ errorLabelsContain: ["UnknownTransactionCommitResult"]
224
+ errorLabelsOmit: ["TransientTransactionError"]
225
+
226
+ expectations:
227
+ - command_started_event:
228
+ command:
229
+ insert: *collection_name
230
+ documents:
231
+ - _id: 1
232
+ ordered: true
233
+ readConcern:
234
+ lsid: session0
235
+ txnNumber:
236
+ $numberLong: "1"
237
+ startTransaction: true
238
+ autocommit: false
239
+ writeConcern:
240
+ command_name: insert
241
+ database_name: *database_name
242
+ - command_started_event:
243
+ command:
244
+ commitTransaction: 1
245
+ lsid: session0
246
+ txnNumber:
247
+ $numberLong: "1"
248
+ startTransaction:
249
+ autocommit: false
250
+ writeConcern:
251
+ recoveryToken: 42
252
+ command_name: commitTransaction
253
+ database_name: admin
254
+ - command_started_event:
255
+ command:
256
+ commitTransaction: 1
257
+ lsid: session0
258
+ txnNumber:
259
+ $numberLong: "1"
260
+ startTransaction:
261
+ autocommit: false
262
+ # commitTransaction applies w:majority on retries
263
+ writeConcern: { w: majority, wtimeout: 10000 }
264
+ recoveryToken: 42
265
+ command_name: commitTransaction
266
+ database_name: admin
267
+
268
+ outcome:
269
+ collection:
270
+ data: []
271
+
272
+ - description: abortTransaction sends recoveryToken
273
+ useMultipleMongoses: true
274
+ operations:
275
+ - name: startTransaction
276
+ object: session0
277
+ - name: insertOne
278
+ object: collection
279
+ arguments:
280
+ session: session0
281
+ document:
282
+ _id: 1
283
+ result:
284
+ insertedId: 1
285
+ # Enable the fail point only on the Mongos that session0 is pinned to.
286
+ - name: targetedFailPoint
287
+ object: testRunner
288
+ arguments:
289
+ session: session0
290
+ failPoint:
291
+ configureFailPoint: failCommand
292
+ mode: { times: 1 }
293
+ data:
294
+ failCommands: ["abortTransaction"]
295
+ closeConnection: true
296
+ # The first abortTransaction sees a retryable connection error due to
297
+ # the fail point. The retry attempt on a new mongos will send the
298
+ # recoveryToken. Note that the retry attempt will also fail because the
299
+ # server does not yet support aborting from a new mongos, however this
300
+ # operation should "succeed" since abortTransaction ignores errors.
301
+ - name: abortTransaction
302
+ object: session0
303
+
304
+ expectations:
305
+ - command_started_event:
306
+ command:
307
+ insert: *collection_name
308
+ documents:
309
+ - _id: 1
310
+ ordered: true
311
+ readConcern:
312
+ lsid: session0
313
+ txnNumber:
314
+ $numberLong: "1"
315
+ startTransaction: true
316
+ autocommit: false
317
+ writeConcern:
318
+ command_name: insert
319
+ database_name: *database_name
320
+ - command_started_event:
321
+ command:
322
+ abortTransaction: 1
323
+ lsid: session0
324
+ txnNumber:
325
+ $numberLong: "1"
326
+ startTransaction:
327
+ autocommit: false
328
+ writeConcern:
329
+ recoveryToken: 42
330
+ command_name: abortTransaction
331
+ database_name: admin
332
+ - command_started_event:
333
+ command:
334
+ abortTransaction: 1
335
+ lsid: session0
336
+ txnNumber:
337
+ $numberLong: "1"
338
+ startTransaction:
339
+ autocommit: false
340
+ writeConcern:
341
+ recoveryToken: 42
342
+ command_name: abortTransaction
343
+ database_name: admin
344
+
345
+ outcome:
346
+ collection:
347
+ data: []
@@ -0,0 +1,557 @@
1
+ # Test that all the operations go to the same mongos.
2
+ #
3
+ # In tests that don't include command-started events the assertion is implicit:
4
+ # that all the read operations succeed. If the driver does not properly pin to
5
+ # a single mongos then one of the operations in a transaction will eventually
6
+ # be sent to a different mongos, which is unaware of the transaction, and the
7
+ # mongos will return a command error. An example of such an error is:
8
+ # {
9
+ # 'ok': 0.0,
10
+ # 'errmsg': 'cannot continue txnId -1 for session 28938f50-9d29-4ca5-8de5-ddaf261267c4 - 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= with txnId 1',
11
+ # 'code': 251,
12
+ # 'codeName': 'NoSuchTransaction',
13
+ # 'errorLabels': ['TransientTransactionError']
14
+ # }
15
+ runOn:
16
+ -
17
+ minServerVersion: "4.1.8"
18
+ topology: ["sharded"]
19
+
20
+ database_name: &database_name "transaction-tests"
21
+ collection_name: &collection_name "test"
22
+
23
+ data: &data
24
+ - {_id: 1}
25
+ - {_id: 2}
26
+
27
+ tests:
28
+ - description: countDocuments
29
+ useMultipleMongoses: true
30
+ operations:
31
+ - &startTransaction
32
+ name: startTransaction
33
+ object: session0
34
+ - &countDocuments
35
+ name: countDocuments
36
+ object: collection
37
+ arguments:
38
+ filter:
39
+ _id: 2
40
+ session: session0
41
+ result: 1
42
+ - *countDocuments
43
+ - *countDocuments
44
+ - *countDocuments
45
+ - *countDocuments
46
+ - *countDocuments
47
+ - *countDocuments
48
+ - *countDocuments
49
+ - &commitTransaction
50
+ name: commitTransaction
51
+ object: session0
52
+
53
+ outcome:
54
+ collection:
55
+ data: *data
56
+
57
+ - description: distinct
58
+ useMultipleMongoses: true
59
+ operations:
60
+ - *startTransaction
61
+ - &distinct
62
+ name: distinct
63
+ object: collection
64
+ arguments:
65
+ fieldName: _id
66
+ session: session0
67
+ result: [1, 2]
68
+ - *distinct
69
+ - *distinct
70
+ - *distinct
71
+ - *distinct
72
+ - *distinct
73
+ - *distinct
74
+ - *distinct
75
+ - *commitTransaction
76
+
77
+ outcome:
78
+ collection:
79
+ data: *data
80
+
81
+ - description: find
82
+ useMultipleMongoses: true
83
+ operations:
84
+ - name: startTransaction
85
+ object: session0
86
+ - &find
87
+ name: find
88
+ object: collection
89
+ arguments:
90
+ filter:
91
+ _id: 2
92
+ session: session0
93
+ result:
94
+ - {_id: 2}
95
+ - *find
96
+ - *find
97
+ - *find
98
+ - *find
99
+ - *find
100
+ - *find
101
+ - *find
102
+ - *commitTransaction
103
+
104
+ outcome:
105
+ collection:
106
+ data: *data
107
+
108
+ - description: insertOne
109
+ useMultipleMongoses: true
110
+ operations:
111
+ - name: startTransaction
112
+ object: session0
113
+ - name: insertOne
114
+ object: collection
115
+ arguments:
116
+ document:
117
+ _id: 3
118
+ session: session0
119
+ result:
120
+ insertedId: 3
121
+ - name: insertOne
122
+ object: collection
123
+ arguments:
124
+ document:
125
+ _id: 4
126
+ session: session0
127
+ result:
128
+ insertedId: 4
129
+ - name: insertOne
130
+ object: collection
131
+ arguments:
132
+ document:
133
+ _id: 5
134
+ session: session0
135
+ result:
136
+ insertedId: 5
137
+ - name: insertOne
138
+ object: collection
139
+ arguments:
140
+ document:
141
+ _id: 6
142
+ session: session0
143
+ result:
144
+ insertedId: 6
145
+ - name: insertOne
146
+ object: collection
147
+ arguments:
148
+ document:
149
+ _id: 7
150
+ session: session0
151
+ result:
152
+ insertedId: 7
153
+ - name: insertOne
154
+ object: collection
155
+ arguments:
156
+ document:
157
+ _id: 8
158
+ session: session0
159
+ result:
160
+ insertedId: 8
161
+ - name: insertOne
162
+ object: collection
163
+ arguments:
164
+ document:
165
+ _id: 9
166
+ session: session0
167
+ result:
168
+ insertedId: 9
169
+ - name: insertOne
170
+ object: collection
171
+ arguments:
172
+ document:
173
+ _id: 10
174
+ session: session0
175
+ result:
176
+ insertedId: 10
177
+ - *commitTransaction
178
+
179
+ outcome:
180
+ collection:
181
+ data:
182
+ - {_id: 1}
183
+ - {_id: 2}
184
+ - {_id: 3}
185
+ - {_id: 4}
186
+ - {_id: 5}
187
+ - {_id: 6}
188
+ - {_id: 7}
189
+ - {_id: 8}
190
+ - {_id: 9}
191
+ - {_id: 10}
192
+
193
+ - description: mixed read write operations
194
+ useMultipleMongoses: true
195
+ operations:
196
+ - name: startTransaction
197
+ object: session0
198
+ - name: insertOne
199
+ object: collection
200
+ arguments:
201
+ document:
202
+ _id: 3
203
+ session: session0
204
+ result:
205
+ insertedId: 3
206
+ - &countDocuments
207
+ name: countDocuments
208
+ object: collection
209
+ arguments:
210
+ filter:
211
+ _id: 3
212
+ session: session0
213
+ result: 1
214
+ - *countDocuments
215
+ - *countDocuments
216
+ - *countDocuments
217
+ - *countDocuments
218
+ - name: insertOne
219
+ object: collection
220
+ arguments:
221
+ document:
222
+ _id: 4
223
+ session: session0
224
+ result:
225
+ insertedId: 4
226
+ - name: insertOne
227
+ object: collection
228
+ arguments:
229
+ document:
230
+ _id: 5
231
+ session: session0
232
+ result:
233
+ insertedId: 5
234
+ - name: insertOne
235
+ object: collection
236
+ arguments:
237
+ document:
238
+ _id: 6
239
+ session: session0
240
+ result:
241
+ insertedId: 6
242
+ - name: insertOne
243
+ object: collection
244
+ arguments:
245
+ document:
246
+ _id: 7
247
+ session: session0
248
+ result:
249
+ insertedId: 7
250
+ - *commitTransaction
251
+
252
+ outcome:
253
+ collection:
254
+ data:
255
+ - {_id: 1}
256
+ - {_id: 2}
257
+ - {_id: 3}
258
+ - {_id: 4}
259
+ - {_id: 5}
260
+ - {_id: 6}
261
+ - {_id: 7}
262
+
263
+ - description: multiple commits
264
+ useMultipleMongoses: true
265
+ operations:
266
+ - name: startTransaction
267
+ object: session0
268
+ - name: insertMany
269
+ object: collection
270
+ arguments:
271
+ documents:
272
+ - _id: 3
273
+ - _id: 4
274
+ session: session0
275
+ result:
276
+ insertedIds: {0: 3, 1: 4}
277
+ # Session is pinned and remains pinned after successful commits.
278
+ - &assertSessionPinned
279
+ name: assertSessionPinned
280
+ object: testRunner
281
+ arguments:
282
+ session: session0
283
+ - *commitTransaction
284
+ - *assertSessionPinned
285
+ - *commitTransaction
286
+ - *commitTransaction
287
+ - *commitTransaction
288
+ - *commitTransaction
289
+ - *commitTransaction
290
+ - *commitTransaction
291
+ - *commitTransaction
292
+ - *commitTransaction
293
+ - *commitTransaction
294
+ - *assertSessionPinned
295
+
296
+ outcome:
297
+ collection:
298
+ data:
299
+ - {_id: 1}
300
+ - {_id: 2}
301
+ - {_id: 3}
302
+ - {_id: 4}
303
+
304
+ - description: remain pinned after non-transient error on commit
305
+ useMultipleMongoses: true
306
+ operations:
307
+ - name: startTransaction
308
+ object: session0
309
+ - name: insertMany
310
+ object: collection
311
+ arguments:
312
+ documents:
313
+ - _id: 3
314
+ - _id: 4
315
+ session: session0
316
+ result:
317
+ insertedIds: {0: 3, 1: 4}
318
+ # Session is pinned.
319
+ - *assertSessionPinned
320
+ # Fail the commit with a non-transient error, eg MaxTimeMSExpired.
321
+ - name: targetedFailPoint
322
+ object: testRunner
323
+ arguments:
324
+ session: session0
325
+ failPoint:
326
+ configureFailPoint: failCommand
327
+ mode: { times: 1 }
328
+ data:
329
+ failCommands: ["commitTransaction"]
330
+ # https://jira.mongodb.org/browse/SPEC-1378
331
+ errorCode: 51 # not MaxTimeMSExpired
332
+ - name: commitTransaction
333
+ object: session0
334
+ result:
335
+ errorLabelsOmit: ["TransientTransactionError"]
336
+ errorCode: 51
337
+ - *assertSessionPinned
338
+ # The next commit should succeed.
339
+ - name: commitTransaction
340
+ object: session0
341
+ - *assertSessionPinned
342
+
343
+ outcome:
344
+ collection:
345
+ data:
346
+ - {_id: 1}
347
+ - {_id: 2}
348
+ - {_id: 3}
349
+ - {_id: 4}
350
+
351
+ - description: unpin after transient error within a transaction
352
+ useMultipleMongoses: true
353
+ operations:
354
+ - name: startTransaction
355
+ object: session0
356
+ - name: insertOne
357
+ object: collection
358
+ arguments:
359
+ session: session0
360
+ document:
361
+ _id: 3
362
+ result:
363
+ insertedId: 3
364
+ # Enable the fail point only on the Mongos that session0 is pinned to.
365
+ - name: targetedFailPoint
366
+ object: testRunner
367
+ arguments:
368
+ session: session0
369
+ failPoint:
370
+ configureFailPoint: failCommand
371
+ mode: { times: 1 }
372
+ data:
373
+ failCommands: ["insert"]
374
+ closeConnection: true
375
+ - name: insertOne
376
+ object: collection
377
+ arguments:
378
+ session: session0
379
+ document:
380
+ _id: 4
381
+ result:
382
+ errorLabelsContain: ["TransientTransactionError"]
383
+ errorLabelsOmit: ["UnknownTransactionCommitResult"]
384
+ # Session unpins from the first mongos after the insert error and
385
+ # abortTransaction succeeds immediately on any mongos.
386
+ - name: abortTransaction
387
+ object: session0
388
+
389
+ expectations:
390
+ - command_started_event:
391
+ command:
392
+ insert: *collection_name
393
+ documents:
394
+ - _id: 3
395
+ ordered: true
396
+ readConcern:
397
+ lsid: session0
398
+ txnNumber:
399
+ $numberLong: "1"
400
+ startTransaction: true
401
+ autocommit: false
402
+ writeConcern:
403
+ command_name: insert
404
+ database_name: *database_name
405
+ - command_started_event:
406
+ command:
407
+ insert: *collection_name
408
+ documents:
409
+ - _id: 4
410
+ ordered: true
411
+ readConcern:
412
+ lsid: session0
413
+ txnNumber:
414
+ $numberLong: "1"
415
+ startTransaction:
416
+ autocommit: false
417
+ writeConcern:
418
+ command_name: insert
419
+ database_name: *database_name
420
+ - command_started_event:
421
+ command:
422
+ abortTransaction: 1
423
+ lsid: session0
424
+ txnNumber:
425
+ $numberLong: "1"
426
+ startTransaction:
427
+ autocommit: false
428
+ writeConcern:
429
+ recoveryToken: 42
430
+ command_name: abortTransaction
431
+ database_name: admin
432
+
433
+ outcome:
434
+ collection:
435
+ data:
436
+ - _id: 1
437
+ - _id: 2
438
+
439
+ # Applications should not run commitTransaction after transient errors but
440
+ # the transactions API allows it and this test confirms unpinning behavior.
441
+ # In a sharded cluster, a transient error within a transaction unpins the
442
+ # session. This way a subsequent abort can "succeed" immediately instead of
443
+ # blocking for serverSelectionTimeoutMS in the case the mongos went down.
444
+ # However since the abortTransaction helper ignores errors, this test uses
445
+ # commitTransaction to prove the session was unpinned.
446
+ - description: unpin after transient error within a transaction and commit
447
+ useMultipleMongoses: true
448
+ clientOptions:
449
+ # Increase heartbeatFrequencyMS to avoid the race condition where an in
450
+ # flight heartbeat refreshes the first mongoes' SDAM state in between
451
+ # the insert connection error and the single commit attempt.
452
+ heartbeatFrequencyMS: 30000
453
+ operations:
454
+ - name: startTransaction
455
+ object: session0
456
+ - name: insertOne
457
+ object: collection
458
+ arguments:
459
+ session: session0
460
+ document:
461
+ _id: 3
462
+ result:
463
+ insertedId: 3
464
+ # Enable the fail point only on the Mongos that session0 is pinned to.
465
+ # Fail isMaster to prevent the heartbeat requested directly after the
466
+ # insert error from racing with server selection for the commit.
467
+ # Note: times: 7 is slightly artbitrary but it accounts for one failed
468
+ # insert and some SDAM heartbeats. A test runner will have multiple
469
+ # clients connected to this server so this fail point configuration
470
+ # is also racy.
471
+ - name: targetedFailPoint
472
+ object: testRunner
473
+ arguments:
474
+ session: session0
475
+ failPoint:
476
+ configureFailPoint: failCommand
477
+ mode: { times: 7 }
478
+ data:
479
+ failCommands: ["insert", "isMaster"]
480
+ closeConnection: true
481
+ - name: insertOne
482
+ object: collection
483
+ arguments:
484
+ session: session0
485
+ document:
486
+ _id: 4
487
+ result:
488
+ errorLabelsContain: ["TransientTransactionError"]
489
+ errorLabelsOmit: ["UnknownTransactionCommitResult"]
490
+ # Session unpins from the first mongos after the insert error and
491
+ # commitTransaction selects the second mongos which is unaware of the
492
+ # transaction and therefore fails with NoSuchTransaction error. If this
493
+ # commit succeeds it indicates a bug, either:
494
+ # - the driver mistakenly remained pinned even after the insert error, or
495
+ # - the test client was initialized with a single mongos seed
496
+ #
497
+ # Note that the commit attempt should not select the original mongos
498
+ # because that server's SDAM state is reset by the connection error,
499
+ # heartbeatFrequencyMS is high, and subsequent isMaster heartbeats
500
+ # should fail.
501
+ - name: commitTransaction
502
+ object: session0
503
+ result:
504
+ errorLabelsContain: ["TransientTransactionError"]
505
+ errorLabelsOmit: ["UnknownTransactionCommitResult"]
506
+ errorCodeName: NoSuchTransaction
507
+
508
+
509
+ expectations:
510
+ - command_started_event:
511
+ command:
512
+ insert: *collection_name
513
+ documents:
514
+ - _id: 3
515
+ ordered: true
516
+ readConcern:
517
+ lsid: session0
518
+ txnNumber:
519
+ $numberLong: "1"
520
+ startTransaction: true
521
+ autocommit: false
522
+ writeConcern:
523
+ command_name: insert
524
+ database_name: *database_name
525
+ - command_started_event:
526
+ command:
527
+ insert: *collection_name
528
+ documents:
529
+ - _id: 4
530
+ ordered: true
531
+ readConcern:
532
+ lsid: session0
533
+ txnNumber:
534
+ $numberLong: "1"
535
+ startTransaction:
536
+ autocommit: false
537
+ writeConcern:
538
+ command_name: insert
539
+ database_name: *database_name
540
+ - command_started_event:
541
+ command:
542
+ commitTransaction: 1
543
+ lsid: session0
544
+ txnNumber:
545
+ $numberLong: "1"
546
+ startTransaction:
547
+ autocommit: false
548
+ writeConcern:
549
+ recoveryToken: 42
550
+ command_name: commitTransaction
551
+ database_name: admin
552
+
553
+ outcome:
554
+ collection:
555
+ data:
556
+ - _id: 1
557
+ - _id: 2