/jstests/core/txns/transactions_profiling.js

https://github.com/paralect/mongo · JavaScript · 242 lines · 189 code · 36 blank · 17 comment · 0 complexity · aa157aacff28f2dbf8463ef207356560 MD5 · raw file

  1. // Test profiling for commands in multi-document transactions.
  2. // @tags: [uses_transactions]
  3. (function() {
  4. "use strict";
  5. load("jstests/libs/profiler.js"); // For getLatestProfilerEntry.
  6. const dbName = "test";
  7. const collName = "transactions_profiling";
  8. const testDB = db.getSiblingDB(dbName);
  9. testDB[collName].drop({writeConcern: {w: "majority"}});
  10. testDB.setProfilingLevel(2);
  11. const sessionOptions = {
  12. causalConsistency: false
  13. };
  14. let session = testDB.getMongo().startSession(sessionOptions);
  15. let sessionDB = session.getDatabase(dbName);
  16. let sessionColl = sessionDB[collName];
  17. assert.commandWorked(sessionColl.insert({_id: "findAndModify-doc"}));
  18. assert.commandWorked(sessionColl.insert({_id: "delete-doc"}));
  19. assert.commandWorked(sessionColl.insert({_id: "multi-delete-doc-1"}));
  20. assert.commandWorked(sessionColl.insert({_id: "multi-delete-doc-2"}));
  21. assert.commandWorked(sessionColl.insert({_id: "multi-delete-doc-3"}));
  22. assert.commandWorked(sessionColl.insert({_id: "multi-delete-doc-4"}));
  23. assert.commandWorked(sessionColl.insert({_id: "read-doc"}));
  24. assert.commandWorked(sessionColl.insert({_id: "update-doc"}));
  25. assert.commandWorked(sessionColl.insert({_id: "multi-update-doc-1"}));
  26. assert.commandWorked(sessionColl.insert({_id: "multi-update-doc-2"}));
  27. assert.commandWorked(testDB.runCommand({
  28. createIndexes: collName,
  29. indexes: [{key: {haystack: "geoHaystack", a: 1}, name: "haystack_geo", bucketSize: 1}],
  30. writeConcern: {w: "majority"}
  31. }));
  32. jsTestLog("Test commands that can use shell helpers.");
  33. session.startTransaction({readConcern: {level: "snapshot"}, writeConcern: {w: "majority"}});
  34. jsTestLog("Test aggregate.");
  35. assert.eq(1, sessionColl.aggregate([{$match: {_id: "read-doc"}}]).itcount());
  36. let profileObj = getLatestProfilerEntry(testDB);
  37. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  38. assert.eq(profileObj.op, "command", tojson(profileObj));
  39. assert.eq(profileObj.command.aggregate, sessionColl.getName(), tojson(profileObj));
  40. assert.eq(profileObj.nreturned, 1, tojson(profileObj));
  41. jsTestLog("Test delete.");
  42. assert.commandWorked(sessionColl.deleteOne({_id: "delete-doc"}));
  43. profileObj = getLatestProfilerEntry(testDB);
  44. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  45. assert.eq(profileObj.op, "remove", tojson(profileObj));
  46. assert.eq(profileObj.ndeleted, 1, tojson(profileObj));
  47. jsTestLog("Test multi delete.");
  48. assert.commandWorked(
  49. sessionColl.deleteMany({_id: {$in: ["multi-delete-doc-1", "multi-delete-doc-2"]}}));
  50. profileObj = getLatestProfilerEntry(testDB);
  51. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  52. assert.eq(profileObj.op, "remove", tojson(profileObj));
  53. assert.eq(profileObj.ndeleted, 2, tojson(profileObj));
  54. jsTestLog("Test batch delete.");
  55. assert.commandWorked(sessionDB.runCommand({
  56. delete: collName,
  57. deletes:
  58. [{q: {_id: "multi-delete-doc-3"}, limit: 1}, {q: {_id: "multi-delete-doc-4"}, limit: 1}]
  59. }));
  60. // We see the profile entry from the second delete.
  61. profileObj = getLatestProfilerEntry(testDB);
  62. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  63. assert.eq(profileObj.op, "remove", tojson(profileObj));
  64. assert.eq(profileObj.ndeleted, 1, tojson(profileObj));
  65. jsTestLog("Test distinct.");
  66. assert.eq(["read-doc"], sessionColl.distinct("_id", {_id: "read-doc"}));
  67. profileObj = getLatestProfilerEntry(testDB);
  68. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  69. assert.eq(profileObj.op, "command", tojson(profileObj));
  70. assert.eq(profileObj.command.distinct, sessionColl.getName(), tojson(profileObj));
  71. jsTestLog("Test find.");
  72. assert.eq(1, sessionColl.find({_id: "read-doc"}).itcount());
  73. profileObj = getLatestProfilerEntry(testDB);
  74. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  75. assert.eq(profileObj.op, "query", tojson(profileObj));
  76. assert.eq(profileObj.nreturned, 1, tojson(profileObj));
  77. jsTestLog("Test findAndModify.");
  78. assert.eq({_id: "findAndModify-doc", updated: true},
  79. sessionColl.findAndModify(
  80. {query: {_id: "findAndModify-doc"}, update: {$set: {updated: true}}, new: true}));
  81. profileObj = getLatestProfilerEntry(testDB);
  82. assert.eq(profileObj.op, "command", tojson(profileObj));
  83. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  84. assert.eq(profileObj.command.findandmodify, sessionColl.getName(), tojson(profileObj));
  85. assert.eq(profileObj.nMatched, 1, tojson(profileObj));
  86. assert.eq(profileObj.nModified, 1, tojson(profileObj));
  87. jsTestLog("Test geoSearch.");
  88. assert.commandWorked(
  89. sessionDB.runCommand({geoSearch: collName, near: [0, 0], maxDistance: 1, search: {a: 1}}));
  90. profileObj = getLatestProfilerEntry(testDB);
  91. assert.eq(profileObj.op, "command", tojson(profileObj));
  92. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  93. assert.eq(profileObj.command.geoSearch, sessionColl.getName(), tojson(profileObj));
  94. jsTestLog("Test getMore.");
  95. let res = assert.commandWorked(
  96. sessionDB.runCommand({find: collName, filter: {_id: "read-doc"}, batchSize: 0}));
  97. assert(res.hasOwnProperty("cursor"), tojson(res));
  98. assert(res.cursor.hasOwnProperty("id"), tojson(res));
  99. let cursorId = res.cursor.id;
  100. res = assert.commandWorked(sessionDB.runCommand({getMore: cursorId, collection: collName}));
  101. assert.eq([{_id: "read-doc"}], res.cursor.nextBatch, tojson(res));
  102. profileObj = getLatestProfilerEntry(testDB);
  103. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  104. assert.eq(profileObj.op, "getmore", tojson(profileObj));
  105. assert.eq(profileObj.nreturned, 1, tojson(profileObj));
  106. jsTestLog("Test insert.");
  107. assert.commandWorked(sessionColl.insert({_id: "insert-doc"}));
  108. profileObj = getLatestProfilerEntry(testDB);
  109. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  110. assert.eq(profileObj.op, "insert", tojson(profileObj));
  111. assert.eq(profileObj.ninserted, 1, tojson(profileObj));
  112. jsTestLog("Test update.");
  113. assert.commandWorked(sessionColl.update({_id: "update-doc"}, {$set: {updated: true}}));
  114. profileObj = getLatestProfilerEntry(testDB);
  115. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  116. assert.eq(profileObj.op, "update", tojson(profileObj));
  117. assert.eq(profileObj.nMatched, 1, tojson(profileObj));
  118. assert.eq(profileObj.nModified, 1, tojson(profileObj));
  119. jsTestLog("Test multi update.");
  120. assert.commandWorked(sessionColl.updateMany(
  121. {_id: {$in: ["multi-update-doc-1", "multi-update-doc-2"]}}, {$set: {updated: true}}));
  122. profileObj = getLatestProfilerEntry(testDB);
  123. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  124. assert.eq(profileObj.op, "update", tojson(profileObj));
  125. assert.eq(profileObj.nMatched, 2, tojson(profileObj));
  126. assert.eq(profileObj.nModified, 2, tojson(profileObj));
  127. jsTestLog("Test batch update.");
  128. assert.commandWorked(sessionDB.runCommand({
  129. update: collName,
  130. updates: [
  131. {q: {_id: "multi-update-doc-1"}, u: {$set: {batch_updated: true}}},
  132. {q: {_id: "multi-update-doc-2"}, u: {$set: {batch_updated: true}}}
  133. ]
  134. }));
  135. // We see the profile entry from the second update.
  136. profileObj = getLatestProfilerEntry(testDB);
  137. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  138. assert.eq(profileObj.op, "update", tojson(profileObj));
  139. assert.eq(profileObj.nMatched, 1, tojson(profileObj));
  140. assert.eq(profileObj.nModified, 1, tojson(profileObj));
  141. jsTestLog("Committing transaction.");
  142. assert.commandWorked(session.commitTransaction_forTesting());
  143. jsTestLog("Test delete with a write conflict.");
  144. assert.commandWorked(sessionColl.insert({_id: "delete-doc"}, {writeConcern: {w: "majority"}}));
  145. session.startTransaction({readConcern: {level: "snapshot"}, writeConcern: {w: "majority"}});
  146. // Perform an operation in the transaction to establish the snapshot.
  147. assert.eq(1, sessionColl.find({_id: "read-doc"}).itcount());
  148. // Update the document outside of the transaction.
  149. assert.commandWorked(testDB[collName].update({_id: "delete-doc"}, {$set: {conflict: true}}));
  150. // Deleting the document in the transaction fails, but profiling is still successful.
  151. assert.throws(function() {
  152. sessionColl.deleteOne({_id: "delete-doc"});
  153. });
  154. profileObj = getLatestProfilerEntry(testDB);
  155. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  156. assert.eq(profileObj.op, "remove", tojson(profileObj));
  157. assert.eq(profileObj.errCode, ErrorCodes.WriteConflict, tojson(profileObj));
  158. assert.commandFailedWithCode(session.abortTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
  159. jsTestLog("Test findAndModify with a write conflict.");
  160. session.startTransaction({readConcern: {level: "snapshot"}, writeConcern: {w: "majority"}});
  161. // Perform an operation in the transaction to establish the snapshot.
  162. assert.eq(1, sessionColl.find({_id: "read-doc"}).itcount());
  163. // Update the document outside of the transaction.
  164. assert.commandWorked(testDB[collName].update({_id: "findAndModify-doc"}, {$set: {conflict: true}}));
  165. // Modifying the document in the transaction fails, but profiling is still successful.
  166. assert.throws(function() {
  167. sessionColl.findAndModify(
  168. {query: {_id: "findAndModify-doc"}, update: {$set: {conflict: false}}});
  169. });
  170. profileObj = getLatestProfilerEntry(testDB);
  171. assert.eq(profileObj.op, "command", tojson(profileObj));
  172. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  173. assert.eq(profileObj.command.findandmodify, sessionColl.getName(), tojson(profileObj));
  174. assert.eq(profileObj.errCode, ErrorCodes.WriteConflict, tojson(profileObj));
  175. assert.commandFailedWithCode(session.abortTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
  176. jsTestLog("Test insert with a write conflict.");
  177. session.startTransaction({readConcern: {level: "snapshot"}, writeConcern: {w: "majority"}});
  178. // Perform an operation in the transaction to establish the snapshot.
  179. assert.eq(1, sessionColl.find({_id: "read-doc"}).itcount());
  180. // Insert a document outside of the transaction.
  181. assert.commandWorked(testDB[collName].insert({_id: "conflict-doc"}));
  182. // Inserting a document with the same _id in the transaction fails, but profiling is still
  183. // successful.
  184. assert.commandFailedWithCode(sessionColl.insert({_id: "conflict-doc"}), ErrorCodes.WriteConflict);
  185. profileObj = getLatestProfilerEntry(testDB);
  186. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  187. assert.eq(profileObj.op, "insert", tojson(profileObj));
  188. assert.eq(profileObj.ninserted, 0, tojson(profileObj));
  189. assert.eq(profileObj.errCode, ErrorCodes.WriteConflict, tojson(profileObj));
  190. assert.commandFailedWithCode(session.abortTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
  191. jsTestLog("Test update with a write conflict.");
  192. session.startTransaction({readConcern: {level: "snapshot"}, writeConcern: {w: "majority"}});
  193. // Perform an operation in the transaction to establish the snapshot.
  194. assert.eq(1, sessionColl.find({_id: "read-doc"}).itcount());
  195. // Update the document outside of the transaction.
  196. assert.commandWorked(testDB[collName].update({_id: "update-doc"}, {$set: {conflict: true}}));
  197. // Updating the document in the transaction fails, but profiling is still successful.
  198. assert.commandFailedWithCode(sessionColl.update({_id: "update-doc"}, {$set: {conflict: false}}),
  199. ErrorCodes.WriteConflict);
  200. profileObj = getLatestProfilerEntry(testDB);
  201. assert.eq(profileObj.ns, sessionColl.getFullName(), tojson(profileObj));
  202. assert.eq(profileObj.op, "update", tojson(profileObj));
  203. assert.eq(profileObj.errCode, ErrorCodes.WriteConflict, tojson(profileObj));
  204. assert.commandFailedWithCode(session.abortTransaction_forTesting(), ErrorCodes.NoSuchTransaction);
  205. session.endSession();
  206. }());