/** * Tests that the writeConcern of a $out/$merge executed on a secondary is propagated to the primary * and is properly respected. * * @tags: [assumes_unsharded_collection, requires_replication] */ (function() { "use strict"; load("jstests/libs/fail_point_util.js"); const replTest = new ReplSetTest({nodes: 2}); replTest.startSet(); replTest.initiate(); replTest.awaitReplication(); const primary = replTest.getPrimary(); const secondary = replTest.getSecondary(); const primaryDB = primary.getDB("test"); const secondaryDB = secondary.getDB("test"); assert.commandWorked(primaryDB.setProfilingLevel(2)); secondaryDB.getMongo().setReadPref("secondary"); const inputCollPrimary = primaryDB.getCollection("inputColl"); const inputCollSecondary = secondaryDB.getCollection("inputColl"); const outColl = primaryDB.getCollection("outColl"); assert.commandWorked(inputCollPrimary.insert({_id: 0, a: 1}, {writeConcern: {w: 2}})); assert.commandWorked(inputCollPrimary.insert({_id: 1, a: 2}, {writeConcern: {w: 2}})); function testWriteConcern(pipeline, comment) { outColl.drop({writeConcern: {w: 2}}); assert.eq( 0, inputCollSecondary.aggregate(pipeline, {writeConcern: {w: 2}, comment: comment}).itcount()); // Verify that the command sent to the primary has the expected w:2 writeConcern attached to it. const arr = primaryDB.system.profile.find({"op": "insert", "command.comment": comment}).toArray(); const expectedWriteConcern = {w: 2, wtimeout: 0, provenance: "clientSupplied"}; assert.eq(1, arr.length); assert.eq(expectedWriteConcern, arr[0].command.writeConcern); outColl.drop({writeConcern: {w: 2}}); // Stop oplog application on the secondary. const failPoint = configureFailPoint(secondary, "rsSyncApplyStop"); failPoint.wait(); const res = secondaryDB.runCommand({ aggregate: "inputColl", pipeline: pipeline, writeConcern: {w: 2, wtimeout: 1000}, comment: comment + "_fail", cursor: {} }); assert.commandFailedWithCode(res, ErrorCodes.WriteConcernFailed); assert(!res.hasOwnProperty("writeErrors")); assert(!res.hasOwnProperty("writeConcernError")); assert.commandWorked( secondary.adminCommand({configureFailPoint: "rsSyncApplyStop", mode: "off"})); } const mergePipeline = [{$merge: {into: outColl.getName(), whenMatched: "fail", whenNotMatched: "insert"}}]; testWriteConcern(mergePipeline, "merge_on_secondary_write_concern"); const outPipeline = [{$group: {_id: "$_id", sum: {$sum: "$a"}}}, {$out: outColl.getName()}]; testWriteConcern(outPipeline, "out_on_secondary_write_concern"); replTest.stopSet(); })();