diff options
author | Martin Neupauer <martin.neupauer@mongodb.com> | 2018-01-18 12:04:01 -0500 |
---|---|---|
committer | Martin Neupauer <martin.neupauer@mongodb.com> | 2018-01-31 15:05:08 -0500 |
commit | 15a7ac9ca54f2d580e2b1d1ab01fe095be1233db (patch) | |
tree | c3628b0d5be60aa6bd911c8c351daa9606f6b060 /jstests/core | |
parent | 3c349c50d8d5a55fa80c1d7ae3ac6a6f6cc82b5e (diff) | |
download | mongo-15a7ac9ca54f2d580e2b1d1ab01fe095be1233db.tar.gz |
SERVER-31484 separate the operation deadline from awaitData deadline in sharded queries.
The deadline has been been already separated for non-sharded queries.
Diffstat (limited to 'jstests/core')
-rw-r--r-- | jstests/core/awaitdata_getmore_cmd.js | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/jstests/core/awaitdata_getmore_cmd.js b/jstests/core/awaitdata_getmore_cmd.js new file mode 100644 index 00000000000..a4c577c7f68 --- /dev/null +++ b/jstests/core/awaitdata_getmore_cmd.js @@ -0,0 +1,193 @@ +// Test the awaitData flag for the find/getMore commands. +// @tags: [requires_replication, requires_getmore] +(function() { + 'use strict'; + + load("jstests/libs/fixture_helpers.js"); + + var cmdRes; + var cursorId; + var defaultBatchSize = 101; + var collName = 'await_data'; + var coll = db[collName]; + + // Create a non-capped collection with 10 documents. + coll.drop(); + for (var i = 0; i < 10; i++) { + assert.writeOK(coll.insert({a: i})); + } + + // Find with tailable flag set should fail for a non-capped collection. + cmdRes = db.runCommand({find: collName, tailable: true}); + assert.commandFailed(cmdRes); + + // Should also fail in the non-capped case if both the tailable and awaitData flags are set. + cmdRes = db.runCommand({find: collName, tailable: true, awaitData: true}); + assert.commandFailed(cmdRes); + + // With a non-existent collection, should succeed but return no data and a closed cursor. + coll.drop(); + cmdRes = assert.commandWorked(db.runCommand({find: collName, tailable: true})); + assert.eq(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.firstBatch.length, 0); + + // Create a capped collection with 10 documents. + assert.commandWorked(db.createCollection(collName, {capped: true, size: 2048})); + for (var i = 0; i < 10; i++) { + assert.writeOK(coll.insert({a: i})); + } + + // GetMore should succeed if query has awaitData but no maxTimeMS is supplied. + cmdRes = db.runCommand({find: collName, batchSize: 2, awaitData: true, tailable: true}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.firstBatch.length, 2); + cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + + // Should also succeed if maxTimeMS is supplied on the original find. + cmdRes = db.runCommand( + {find: collName, batchSize: 2, awaitData: true, tailable: true, maxTimeMS: 2000}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.firstBatch.length, 2); + cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + + // Check that we can set up a tailable cursor over the capped collection. + cmdRes = db.runCommand({find: collName, batchSize: 5, awaitData: true, tailable: true}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.firstBatch.length, 5); + + // Check that tailing the capped collection with awaitData eventually ends up returning an empty + // batch after hitting the timeout. + cmdRes = db.runCommand({find: collName, batchSize: 2, awaitData: true, tailable: true}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.firstBatch.length, 2); + + // Issue getMore until we get an empty batch of results. + cmdRes = db.runCommand({ + getMore: cmdRes.cursor.id, + collection: coll.getName(), + batchSize: NumberInt(2), + maxTimeMS: 4000 + }); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + + // Keep issuing getMore until we get an empty batch after the timeout expires. + while (cmdRes.cursor.nextBatch.length > 0) { + var now = new Date(); + cmdRes = db.runCommand({ + getMore: cmdRes.cursor.id, + collection: coll.getName(), + batchSize: NumberInt(2), + maxTimeMS: 4000 + }); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + } + assert.gte((new Date()) - now, 2000); + + // Repeat the test, this time tailing the oplog rather than a user-created capped collection. + // The oplog tailing in not possible on mongos. + if (FixtureHelpers.isReplSet(db)) { + var localDB = db.getSiblingDB("local"); + var oplogColl = localDB.oplog.$main; + + cmdRes = localDB.runCommand( + {find: oplogColl.getName(), batchSize: 2, awaitData: true, tailable: true}); + assert.commandWorked(cmdRes); + if (cmdRes.cursor.id > NumberLong(0)) { + assert.eq(cmdRes.cursor.ns, oplogColl.getFullName()); + assert.eq(cmdRes.cursor.firstBatch.length, 2); + + cmdRes = localDB.runCommand( + {getMore: cmdRes.cursor.id, collection: oplogColl.getName(), maxTimeMS: 1000}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, oplogColl.getFullName()); + + while (cmdRes.cursor.nextBatch.length > 0) { + now = new Date(); + cmdRes = localDB.runCommand( + {getMore: cmdRes.cursor.id, collection: oplogColl.getName(), maxTimeMS: 4000}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, oplogColl.getFullName()); + } + assert.gte((new Date()) - now, 2000); + } + } + + // Test filtered inserts while writing to a capped collection. + // Find with a filter which doesn't match any documents in the collection. + cmdRes = assert.commandWorked(db.runCommand({ + find: collName, + batchSize: 2, + filter: {x: 1}, + awaitData: true, + tailable: true, + comment: "uniquifier_comment" + })); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.firstBatch.length, 0); + + // getMore should time out if we insert a non-matching document. + let insertshell = startParallelShell(function() { + assert.soon( + function() { + return db.currentOp({ + op: "getmore", + "command.collection": "await_data", + "originatingCommand.comment": "uniquifier_comment" + }).inprog.length == 1; + }, + function() { + return tojson(db.currentOp().inprog); + }); + assert.writeOK(db.await_data.insert({x: 0})); + }); + + now = new Date(); + cmdRes = db.runCommand({getMore: cmdRes.cursor.id, collection: collName, maxTimeMS: 4000}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.nextBatch.length, 0); + assert.gte((new Date()) - now, + // SERVER-31502 Add some leniency here since our server-side wait may be woken up + // spuriously. + 3900, + "Insert not matching filter caused awaitData getMore to return prematurely."); + insertshell(); + + // getMore should succeed if we insert a non-matching document followed by a matching one. + insertshell = startParallelShell(function() { + assert.writeOK(db.await_data.insert({x: 0})); + assert.writeOK(db.await_data.insert({_id: "match", x: 1})); + jsTestLog("Written"); + }); + + cmdRes = + db.runCommand({getMore: cmdRes.cursor.id, collection: collName, maxTimeMS: 5 * 60 * 1000}); + assert.commandWorked(cmdRes); + assert.gt(cmdRes.cursor.id, NumberLong(0)); + assert.eq(cmdRes.cursor.ns, coll.getFullName()); + assert.eq(cmdRes.cursor.nextBatch.length, 1); + assert.docEq(cmdRes.cursor.nextBatch[0], {_id: "match", x: 1}); + insertshell(); +})(); |