summaryrefslogtreecommitdiff
path: root/jstests/sharding/out_write_concern.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/sharding/out_write_concern.js')
-rw-r--r--jstests/sharding/out_write_concern.js92
1 files changed, 92 insertions, 0 deletions
diff --git a/jstests/sharding/out_write_concern.js b/jstests/sharding/out_write_concern.js
new file mode 100644
index 00000000000..d4aeb75c1d0
--- /dev/null
+++ b/jstests/sharding/out_write_concern.js
@@ -0,0 +1,92 @@
+// Tests that $out respects the writeConcern set on the original aggregation command.
+(function() {
+ "use strict";
+
+ load("jstests/aggregation/extras/out_helpers.js"); // For withEachOutMode() and isSharded().
+
+ const st = new ShardingTest({shards: 2, rs: {nodes: 3}, config: 1});
+
+ const mongosDB = st.s0.getDB("out_write_concern");
+ const source = mongosDB["source"];
+ const target = mongosDB["target"];
+ const shard0 = st.rs0;
+ const shard1 = st.rs1;
+
+ // Enable sharding on the test DB and ensure its primary is shard0.
+ assert.commandWorked(mongosDB.adminCommand({enableSharding: mongosDB.getName()}));
+ st.ensurePrimaryShard(mongosDB.getName(), st.shard0.shardName);
+
+ function testWriteConcernError(rs) {
+ // Make sure that there are only 2 nodes up so w:3 writes will always time out.
+ const stoppedSecondary = rs.getSecondary();
+ rs.stop(stoppedSecondary);
+
+ // Test that $out correctly returns a WC error.
+ withEachOutMode((mode) => {
+ // Skip mode "replaceCollection" if the target collection is sharded, as it is
+ // unsupported. Also skip mode "replaceCollection" if the test is expecting a timeout
+ // against the non-primary shard, since this mode writes to a temp collection on the
+ // primary only.
+ if (mode == "replaceCollection" && (rs != shard0 || FixtureHelpers.isSharded(target)))
+ return;
+
+ const res = mongosDB.runCommand({
+ aggregate: "source",
+ pipeline: [{$out: {to: "target", mode: mode}}],
+ writeConcern: {w: 3, wtimeout: 100},
+ cursor: {},
+ });
+
+ // $out writeConcern errors are handled differently from normal writeConcern
+ // errors. Rather than returing ok:1 and a WriteConcernError, the entire operation
+ // fails.
+ assert.commandFailedWithCode(res, ErrorCodes.WriteConcernFailed);
+ assert.commandWorked(target.remove({}));
+ });
+
+ // Restart the stopped node and verify that the $out's now pass.
+ rs.restart(rs.getSecondary());
+ rs.awaitReplication();
+ withEachOutMode((mode) => {
+ // "replaceCollection" is banned when the target collection is sharded.
+ if (mode == "replaceCollection" && FixtureHelpers.isSharded(target))
+ return;
+
+ const res = mongosDB.runCommand({
+ aggregate: "source",
+ pipeline: [{$out: {to: "target", mode: mode}}],
+ writeConcern: {w: 3},
+ cursor: {},
+ });
+
+ // Ensure that the write concern is satisfied within a reasonable amount of time. This
+ // prevents the test from hanging if for some reason the write concern can't be
+ // satisfied.
+ assert.soon(() => assert.commandWorked(res), "writeConcern was not satisfied");
+ assert.commandWorked(target.remove({}));
+ });
+ }
+
+ // Test that when both collections are unsharded, all writes are directed to the primary shard.
+ assert.commandWorked(source.insert([{_id: -1}, {_id: 0}, {_id: 1}, {_id: 2}]));
+ testWriteConcernError(shard0);
+
+ // Shard the source collection and continue to expect writes to the primary shard.
+ st.shardColl(source, {_id: 1}, {_id: 0}, {_id: 1}, mongosDB.getName());
+ testWriteConcernError(shard0);
+
+ // Shard the target collection, however make sure that all writes go to the primary shard by
+ // splitting the collection at {_id: 10} and keeping all values in the same chunk.
+ st.shardColl(target, {_id: 1}, {_id: 10}, {_id: 10}, mongosDB.getName());
+ assert.eq(FixtureHelpers.isSharded(target), true);
+ testWriteConcernError(shard0);
+
+ // Write a few documents to the source collection which will be $out-ed to the second shard.
+ assert.commandWorked(source.insert([{_id: 11}, {_id: 12}, {_id: 13}]));
+
+ // Verify that either shard can produce a WriteConcernError since writes are going to both.
+ testWriteConcernError(shard0);
+ testWriteConcernError(shard1);
+
+ st.stop();
+}());