mongo/jstests/sharding/sharding_non_transaction_sn...

161 lines
6.5 KiB
JavaScript

/**
* Tests readConcern level snapshot outside of transactions.
*
* @tags: [
* requires_majority_read_concern,
* requires_persistence,
* ]
*/
import {FeatureFlagUtil} from "jstests/libs/feature_flag_util.js";
import {SnapshotReadsTest} from "jstests/libs/global_snapshot_reads_util.js";
import {ShardingTest} from "jstests/libs/shardingtest.js";
import {findChunksUtil} from "jstests/sharding/libs/find_chunks_util.js";
import {flushRoutersAndRefreshShardMetadata} from "jstests/sharding/libs/sharded_transactions_helpers.js";
const nodeOptions = {
// Set a large snapshot window of 10 minutes for the test.
setParameter: {minSnapshotHistoryWindowInSeconds: 600},
};
const dbName = "test";
const shardedCollName = "shardedColl";
const unshardedCollName = "unshardedColl";
function setUpAllScenarios(st) {
assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
assert.commandWorked(st.s.adminCommand({shardCollection: st.s.getDB(dbName)[shardedCollName] + "", key: {_id: 1}}));
}
let shardingScenarios = {
singleShard: {
compatibleCollections: [shardedCollName, unshardedCollName],
setUp: function () {
const st = new ShardingTest({
mongos: 1,
config: TestData.configShard ? undefined : 1,
shards: {rs0: {nodes: 2}},
other: {configOptions: nodeOptions, rsOptions: nodeOptions},
});
setUpAllScenarios(st);
return st;
},
},
multiShardAllShardReads: {
compatibleCollections: [shardedCollName],
setUp: function () {
let st = new ShardingTest({
shards: {
rs0: {nodes: 2},
rs1: {nodes: 2},
rs2: {nodes: 2},
},
mongos: 1,
config: TestData.configShard ? undefined : 1,
other: {configOptions: nodeOptions, rsOptions: nodeOptions},
});
setUpAllScenarios(st);
const mongos = st.s0;
const ns = dbName + "." + shardedCollName;
// snapshotReadsTest() inserts ids 0-9 and tries snapshot reads on the collection.
assert.commandWorked(st.splitAt(ns, {_id: 4}));
assert.commandWorked(st.splitAt(ns, {_id: 7}));
assert.commandWorked(mongos.adminCommand({moveChunk: ns, find: {_id: 0}, to: st.shard0.shardName}));
assert.commandWorked(mongos.adminCommand({moveChunk: ns, find: {_id: 4}, to: st.shard1.shardName}));
assert.commandWorked(mongos.adminCommand({moveChunk: ns, find: {_id: 7}, to: st.shard2.shardName}));
assert.eq(1, findChunksUtil.countChunksForNs(mongos.getDB("config"), ns, {shard: st.shard0.shardName}));
assert.eq(1, findChunksUtil.countChunksForNs(mongos.getDB("config"), ns, {shard: st.shard1.shardName}));
assert.eq(1, findChunksUtil.countChunksForNs(mongos.getDB("config"), ns, {shard: st.shard2.shardName}));
flushRoutersAndRefreshShardMetadata(st, {ns});
return st;
},
},
// Only two out of three shards have documents.
multiShardSomeShardReads: {
compatibleCollections: [shardedCollName],
setUp: function () {
let st = new ShardingTest({
shards: {
rs0: {nodes: 2},
rs1: {nodes: 2},
rs2: {nodes: 2},
},
mongos: 1,
config: TestData.configShard ? undefined : 1,
other: {configOptions: nodeOptions, rsOptions: nodeOptions},
});
setUpAllScenarios(st);
const mongos = st.s0;
const ns = dbName + "." + shardedCollName;
// snapshotReadsTest() inserts ids 0-9 and tries snapshot reads on the collection.
assert.commandWorked(st.splitAt(ns, {_id: 5}));
assert.commandWorked(mongos.adminCommand({moveChunk: ns, find: {_id: 0}, to: st.shard1.shardName}));
assert.commandWorked(mongos.adminCommand({moveChunk: ns, find: {_id: 7}, to: st.shard2.shardName}));
assert.eq(0, findChunksUtil.countChunksForNs(mongos.getDB("config"), ns, {shard: st.shard0.shardName}));
assert.eq(1, findChunksUtil.countChunksForNs(mongos.getDB("config"), ns, {shard: st.shard1.shardName}));
assert.eq(1, findChunksUtil.countChunksForNs(mongos.getDB("config"), ns, {shard: st.shard2.shardName}));
flushRoutersAndRefreshShardMetadata(st, {ns});
return st;
},
},
};
for (let [scenarioName, scenario] of Object.entries(shardingScenarios)) {
scenario.compatibleCollections.forEach(function (collName) {
jsTestLog(`Run scenario ${scenarioName} with collection ${collName}`);
let st = scenario.setUp();
let primaryAdmin = st.rs0.getPrimary().getDB("admin");
assert.eq(
assert.commandWorked(primaryAdmin.runCommand({getParameter: 1, minSnapshotHistoryWindowInSeconds: 1}))
.minSnapshotHistoryWindowInSeconds,
600,
);
function awaitCommittedFn() {
for (let i = 0; st["rs" + i] !== undefined; i++) {
st["rs" + i].awaitLastOpCommitted();
}
}
if (collName == unshardedCollName) {
// Skip testing with untracked unsharded collections because reads at a point-in-time
// earlier than the latest catalog change (including index DDL) will throw conflicts.
jsTestLog("Skip unsharded collection scenario");
st.stop();
return;
}
// Pass the same DB handle as "primaryDB" and "secondaryDB" params; the test functions will
// send readPreference to mongos to target primary/secondary shard servers.
let db = st.s.getDB(dbName);
let snapshotReadsTest = new SnapshotReadsTest({
primaryDB: db,
secondaryDB: db,
awaitCommittedFn: awaitCommittedFn,
});
snapshotReadsTest.cursorTest({testScenarioName: scenarioName, collName: collName});
if (collName === shardedCollName) {
// "distinct" prohibited on sharded collections.
assert.commandFailedWithCode(
db.runCommand({distinct: collName, key: "_id", readConcern: {level: "snapshot"}}),
ErrorCodes.InvalidOptions,
);
} else {
snapshotReadsTest.distinctTest({testScenarioName: scenarioName, collName: collName});
}
st.stop();
});
}