mongo 2.9.2 → 2.10.0.rc0

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