mongo/jstests/sharding/query/allow_partial_results.js

122 lines
5.2 KiB
JavaScript

/**
* Tests that the 'allowPartialResults' option to find is respected, and that aggregation does not
* accept the 'allowPartialResults' option.
*/
import {ShardingTest} from "jstests/libs/shardingtest.js";
// This test shuts down a shard.
TestData.skipCheckingUUIDsConsistentAcrossCluster = true;
TestData.skipCheckingIndexesConsistentAcrossCluster = true;
TestData.skipCheckShardFilteringMetadata = true;
const dbName = "test";
const collName = "foo";
const ns = dbName + "." + collName;
const st = new ShardingTest({shards: 2});
jsTest.log("Create a sharded collection with one chunk on each of the two shards.");
assert.commandWorked(st.s.adminCommand({enableSharding: dbName, primaryShard: st.shard1.shardName}));
assert.commandWorked(st.s.adminCommand({shardCollection: ns, key: {_id: 1}}));
assert.commandWorked(st.s.adminCommand({split: ns, middle: {_id: 0}}));
assert.commandWorked(st.s.adminCommand({moveChunk: ns, find: {_id: 0}, to: st.shard0.shardName}));
jsTest.log("Insert some data.");
const nDocs = 100;
const coll = st.s0.getDB(dbName)[collName];
let bulk = coll.initializeUnorderedBulkOp();
for (let i = -50; i < 50; i++) {
bulk.insert({_id: i});
}
assert.commandWorked(bulk.execute());
let findRes;
jsTest.log("Without 'allowPartialResults', if all shards are up, find returns all docs.");
findRes = coll.runCommand({find: collName});
assert.commandWorked(findRes);
assert.eq(nDocs, findRes.cursor.firstBatch.length);
assert.eq(undefined, findRes.cursor.partialResultsReturned);
jsTest.log("With 'allowPartialResults: false', if all shards are up, find returns all docs.");
findRes = coll.runCommand({find: collName, allowPartialResults: false});
assert.commandWorked(findRes);
assert.eq(nDocs, findRes.cursor.firstBatch.length);
assert.eq(undefined, findRes.cursor.partialResultsReturned);
// Find with batch size less than the number of documents on each shard so getMore can be run.
let nRemainingDocs = nDocs;
const batchSize = 10;
jsTest.log("With 'allowPartialResults: true', if all shards are up, find returns all docs.");
findRes = coll.runCommand({find: collName, allowPartialResults: true, batchSize: batchSize});
assert.commandWorked(findRes);
assert.eq(batchSize, findRes.cursor.firstBatch.length);
assert.eq(undefined, findRes.cursor.partialResultsReturned);
nRemainingDocs -= batchSize;
jsTest.log("Stopping " + st.shard1.shardName);
st.rs1.stopSet();
nRemainingDocs -= nDocs / 2 - batchSize;
// Do getMore with the returned cursor.
jsTest.log(
"When no getMores are issued to the unreachable shard because mongos has loaded 'batchSize' " +
"docs from each shard in the initial find, getMore does not return partialResultsReturned.",
);
let getMoreRes = coll.runCommand({getMore: findRes.cursor.id, collection: collName, batchSize: batchSize});
assert.commandWorked(getMoreRes);
assert.eq(batchSize, getMoreRes.cursor.nextBatch.length);
assert.eq(undefined, getMoreRes.cursor.partialResultsReturned);
nRemainingDocs -= batchSize;
jsTest.log("When getMores are issued to the unreachable shard, getMore returns partialResultsReturned: 1");
// Use batch size of nRemainingDocs + 1 so that the getMore will wait for the scheduled getMores to
// all the shards.
getMoreRes = coll.runCommand({getMore: findRes.cursor.id, collection: collName, batchSize: nRemainingDocs + 1});
assert.commandWorked(getMoreRes);
assert.eq(nRemainingDocs, getMoreRes.cursor.nextBatch.length);
assert.eq(true, getMoreRes.cursor.partialResultsReturned);
jsTest.log("Without 'allowPartialResults', if some shards are down, find fails.");
assert.commandFailed(coll.runCommand({find: collName}));
jsTest.log("With 'allowPartialResults: false', if some shards are down, find fails.");
assert.commandFailed(coll.runCommand({find: collName, allowPartialResults: false}));
nRemainingDocs = nDocs / 2;
jsTest.log("With 'allowPartialResults: true', if some shards are down, find returns partial results");
findRes = coll.runCommand({find: collName, allowPartialResults: true, batchSize: batchSize});
assert.commandWorked(findRes);
assert.eq(batchSize, findRes.cursor.firstBatch.length);
assert.eq(true, findRes.cursor.partialResultsReturned);
nRemainingDocs -= batchSize;
jsTest.log("getMore after a find that returns partial results returns partialResultsReturned: true");
getMoreRes = coll.runCommand({getMore: findRes.cursor.id, collection: collName, batchSize: batchSize});
assert.commandWorked(getMoreRes);
assert.eq(batchSize, getMoreRes.cursor.nextBatch.length);
assert.eq(true, getMoreRes.cursor.partialResultsReturned);
nRemainingDocs -= batchSize;
jsTest.log("Subsequent getMores should return partialResultsReturned: true regardless of the batch size.");
getMoreRes = coll.runCommand({getMore: findRes.cursor.id, collection: collName});
assert.commandWorked(getMoreRes);
assert.eq(nRemainingDocs, getMoreRes.cursor.nextBatch.length);
assert.eq(true, getMoreRes.cursor.partialResultsReturned);
jsTest.log("The allowPartialResults option does not currently apply to aggregation.");
assert.commandFailedWithCode(
coll.runCommand({
aggregate: collName,
pipeline: [{$project: {_id: 1}}],
cursor: {},
allowPartialResults: true,
}),
[ErrorCodes.FailedToParse, ErrorCodes.IDLUnknownField],
);
st.stop();