summaryrefslogtreecommitdiff
path: root/jstests/sharding/allow_partial_results.js
blob: 55d083537dbf48fe56e503ce680c7bea2a34930d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * Tests that the 'allowPartialResults' option to find is respected, and that aggregation does not
 * accept the 'allowPartialResults' option.
 */

// This test shuts down a shard.
TestData.skipCheckingUUIDsConsistentAcrossCluster = true;
TestData.skipCheckingIndexesConsistentAcrossCluster = true;

(function() {
"use strict";
const dbName = "test";
const collName = "foo";
const ns = dbName + "." + collName;

const st = new ShardingTest({shards: 2});

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());

jsTest.log("Create a sharded collection with one chunk on each of the two shards.");
st.ensurePrimaryShard(dbName, st.shard0.shardName);
assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
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.shard1.shardName}));

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.shard0.shardName);
st.rs0.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, 40415]);

st.stop();
}());