Skip to content

feat: remove top-level write concern options #2630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bulk/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ export abstract class BulkOperationBase {
* bulkOp.find({ h: 8 }).delete();
*
* // Add a replaceOne
* bulkOp.find({ i: 9 }).replaceOne({ j: 10 });
* bulkOp.find({ i: 9 }).replaceOne({writeConcern: { j: 10 }});
*
* // Update using a pipeline (requires Mongodb 4.2 or higher)
* bulk.find({ k: 11, y: { $exists: true }, z: { $exists: true } }).updateOne([
Expand Down
9 changes: 4 additions & 5 deletions src/cmap/wire_protocol/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import type { Document, BSONSerializeOptions } from '../../bson';
import type { Server } from '../../sdam/server';
import type { Topology } from '../../sdam/topology';
import type { ReadPreferenceLike } from '../../read_preference';
import type { WriteConcernOptions, WriteConcern, W } from '../../write_concern';
import type { WriteConcernOptions } from '../../write_concern';
import type { WriteCommandOptions } from './write_command';

/** @internal */
export interface CommandOptions extends BSONSerializeOptions {
export interface CommandOptions extends BSONSerializeOptions, WriteConcernOptions {
// FIXME: NODE-2781

command?: boolean;
slaveOk?: boolean;
/** Specify read preference if command supports it */
Expand All @@ -28,9 +30,6 @@ export interface CommandOptions extends BSONSerializeOptions {

// FIXME: NODE-2802
willRetryWrite?: boolean;

// FIXME: NODE-2781
writeConcern?: WriteConcernOptions | WriteConcern | W;
}

function isClientEncryptionEnabled(server: Server) {
Expand Down
5 changes: 1 addition & 4 deletions src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ import type { Admin } from './admin';

// Allowed parameters
const legalOptionNames = [
'w',
'wtimeout',
'fsync',
'j',
'writeConcern',
'readPreference',
'readPreferenceTags',
'native_parser',
Expand Down
8 changes: 5 additions & 3 deletions src/gridfs-stream/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,11 @@ function doWrite(
function getWriteOptions(stream: GridFSBucketWriteStream): WriteConcernOptions {
const obj: WriteConcernOptions = {};
if (stream.writeConcern) {
obj.w = stream.writeConcern.w;
obj.wtimeout = stream.writeConcern.wtimeout;
obj.j = stream.writeConcern.j;
obj.writeConcern = {
w: stream.writeConcern.w,
wtimeout: stream.writeConcern.wtimeout,
j: stream.writeConcern.j
};
}
return obj;
}
Expand Down
10 changes: 8 additions & 2 deletions src/mongo_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
import { ChangeStream, ChangeStreamOptions } from './change_stream';
import { ReadPreference, ReadPreferenceMode } from './read_preference';
import { MongoError, AnyError } from './error';
import { WriteConcern, WriteConcernOptions } from './write_concern';
import { W, WriteConcern, WriteConcernOptions } from './write_concern';
import { maybePromise, MongoDBNamespace, Callback } from './utils';
import { deprecate } from 'util';
import { connect, validOptions } from './operations/connect';
Expand Down Expand Up @@ -54,7 +54,7 @@ type CleanUpHandlerFunction = (err?: AnyError, result?: any, opts?: any) => Prom
* @public
* @see https://docs.mongodb.com/manual/reference/connection-string
*/
export interface MongoURIOptions extends Pick<WriteConcernOptions, 'journal' | 'w' | 'wtimeoutMS'> {
export interface MongoURIOptions {
/** Specifies the name of the replica set, if the mongod is a member of a replica set. */
replicaSet?: string;
/** Enables or disables TLS/SSL for the connection. */
Expand Down Expand Up @@ -127,6 +127,12 @@ export interface MongoURIOptions extends Pick<WriteConcernOptions, 'journal' | '
retryWrites?: boolean;
/** Allow a driver to force a Single topology type with a connection string containing one host */
directConnection?: boolean;
/** The journal write concern */
journal?: boolean;
/** The write concern */
w?: W;
/** The write concern timeout */
wtimeoutMS?: number;
}

/** @public */
Expand Down
27 changes: 16 additions & 11 deletions src/operations/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ const validOptionNames = [
'acceptableLatencyMS',
'connectWithNoPrimary',
'authSource',
'w',
'wtimeout',
'j',
'writeConcern',
'forceServerObjectId',
'serializeFunctions',
'ignoreUndefined',
Expand All @@ -78,7 +76,6 @@ const validOptionNames = [
'password',
'authMechanism',
'compression',
'fsync',
'readPreferenceTags',
'numberOfRetries',
'auto_reconnect',
Expand Down Expand Up @@ -226,12 +223,6 @@ export function connect(
delete finalOptions.db_options.auth;
}

// `journal` should be translated to `j` for the driver
if (finalOptions.journal != null) {
finalOptions.j = finalOptions.journal;
finalOptions.journal = undefined;
}

// resolve tls options if needed
resolveTLSOptions(finalOptions);

Expand Down Expand Up @@ -422,7 +413,9 @@ function createUnifiedOptions(finalOptions: any, options: any) {
const noMerge = ['readconcern', 'compression', 'autoencryption'];

for (const name in options) {
if (noMerge.indexOf(name.toLowerCase()) !== -1) {
if (name === 'writeConcern') {
finalOptions[name] = { ...finalOptions[name], ...options[name] };
} else if (noMerge.indexOf(name.toLowerCase()) !== -1) {
finalOptions[name] = options[name];
} else if (childOptions.indexOf(name.toLowerCase()) !== -1) {
finalOptions = mergeOptions(finalOptions, options[name], false);
Expand Down Expand Up @@ -561,12 +554,24 @@ function transformUrlOptions(connStrOptions: any) {

if (connStrOpts.wTimeoutMS) {
connStrOpts.wtimeout = connStrOpts.wTimeoutMS;
connStrOpts.wTimeoutMS = undefined;
}

if (connStrOptions.srvHost) {
connStrOpts.srvHost = connStrOptions.srvHost;
}

// Any write concern options from the URL will be top-level, so we manually
// move them options under `object.writeConcern`
const wcKeys = ['w', 'wtimeout', 'j', 'journal', 'fsync'];
for (const key of wcKeys) {
if (connStrOpts[key] !== undefined) {
if (connStrOpts.writeConcern === undefined) connStrOpts.writeConcern = {};
connStrOpts.writeConcern[key] = connStrOpts[key];
connStrOpts[key] = undefined;
}
}

return connStrOpts;
}

Expand Down
3 changes: 0 additions & 3 deletions src/operations/map_reduce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ const exclusionList = [
'readConcern',
'session',
'bypassDocumentValidation',
'w',
'wtimeout',
'j',
'writeConcern',
'raw',
'fieldsAsRaw',
Expand Down
28 changes: 14 additions & 14 deletions src/write_concern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ export type W = number | 'majority';

/** @public */
export interface WriteConcernOptions {
/** Write Concern as an object */
writeConcern?: WriteConcern | WriteConcernSettings;
}

/** @public */
export interface WriteConcernSettings {
/** The write concern */
w?: W;
/** The write concern timeout */
Expand All @@ -15,12 +21,8 @@ export interface WriteConcernOptions {
journal?: boolean;
/** The file sync write concern */
fsync?: boolean | 1;
/** Write Concern as an object */
writeConcern?: WriteConcernOptions | WriteConcern | W;
}

export const writeConcernKeys = ['w', 'j', 'wtimeout', 'fsync'];

/**
* A MongoDB WriteConcern, which describes the level of acknowledgement
* requested from MongoDB for write operations.
Expand Down Expand Up @@ -65,19 +67,17 @@ export class WriteConcern {

/** Construct a WriteConcern given an options object. */
static fromOptions(
options?: WriteConcernOptions | WriteConcern | W,
options?: WriteConcernOptions | WriteConcern,
inherit?: WriteConcernOptions | WriteConcern
): WriteConcern | undefined {
const { fromOptions } = WriteConcern;
if (typeof options === 'undefined') return undefined;
if (typeof options === 'number') return fromOptions({ ...inherit, w: options });
if (typeof options === 'string') return fromOptions({ ...inherit, w: options });
if (options instanceof WriteConcern) return fromOptions({ ...inherit, ...options });
if (options.writeConcern) {
const { writeConcern, ...viable } = { ...inherit, ...options };
return fromOptions(writeConcern, viable);
}
const { w, wtimeout, j, fsync, journal, wtimeoutMS } = { ...inherit, ...options };
inherit = inherit ?? {};
const opts: WriteConcern | WriteConcernSettings | undefined =
options instanceof WriteConcern ? options : options.writeConcern;
const parentOpts: WriteConcern | WriteConcernSettings | undefined =
inherit instanceof WriteConcern ? inherit : inherit.writeConcern;

const { w, wtimeout, j, fsync, journal, wtimeoutMS } = { ...parentOpts, ...opts };
if (
w != null ||
wtimeout != null ||
Expand Down
12 changes: 9 additions & 3 deletions test/examples/transactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,15 @@ describe('examples(transactions):', function () {

// Prereq: Create collections.

await client.db('mydb1').collection('foo').insertOne({ abc: 0 }, { w: 'majority' });

await client.db('mydb2').collection('bar').insertOne({ xyz: 0 }, { w: 'majority' });
await client
.db('mydb1')
.collection('foo')
.insertOne({ abc: 0 }, { writeConcern: { w: 'majority' } });

await client
.db('mydb2')
.collection('bar')
.insertOne({ xyz: 0 }, { writeConcern: { w: 'majority' } });

// Step 1: Start a Client Session
const session = client.startSession();
Expand Down
27 changes: 15 additions & 12 deletions test/functional/aggregation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArray');
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -172,7 +172,7 @@ describe('Aggregation', function () {
'shouldCorrectlyExecuteSimpleAggregationPipelineUsingArguments'
);
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -260,7 +260,7 @@ describe('Aggregation', function () {
'shouldCorrectlyExecuteSimpleAggregationPipelineUsingArguments'
);
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -346,7 +346,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyDoAggWithCursorGet');
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(err).to.not.exist;
expect(result).to.exist;

Expand Down Expand Up @@ -431,7 +431,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyDoAggWithCursorGet');
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -520,7 +520,7 @@ describe('Aggregation', function () {
// Create a collection
const collection = db.collection('shouldCorrectlyDoAggWithCursorGet');
// Insert the docs
collection.insert(docs, { w: 1 }, (err, result) => {
collection.insert(docs, { writeConcern: { w: 1 } }, (err, result) => {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -609,7 +609,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyDoAggWithCursorGet');
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -694,7 +694,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyDoAggWithCursorGet');
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -890,7 +890,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyDoAggWithCursorGetStream');
// Insert the docs
collection.insert(docs, { w: 1 }, function (err, result) {
collection.insert(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -1033,7 +1033,7 @@ describe('Aggregation', function () {
// Create a collection
const collection = db.collection('shouldCorrectlyDoAggWithCursorMaxTimeMSSet');
// Insert the docs
collection.insert(docs, { w: 1 }, (err, result) => {
collection.insert(docs, { writeConcern: { w: 1 } }, (err, result) => {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -1203,7 +1203,7 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyQueryUsingISODate');
// Insert the docs
collection.insertMany(docs, { w: 1 }, function (err, result) {
collection.insertMany(docs, { writeConcern: { w: 1 } }, function (err, result) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down Expand Up @@ -1255,7 +1255,10 @@ describe('Aggregation', function () {
// Create a collection
var collection = db.collection('shouldCorrectlyQueryUsingISODate3');
// Insert the docs
collection.insertMany([{ a: 1 }, { b: 1 }], { w: 1 }, function (err, result) {
collection.insertMany([{ a: 1 }, { b: 1 }], { writeConcern: { w: 1 } }, function (
err,
result
) {
expect(result).to.exist;
expect(err).to.not.exist;

Expand Down
17 changes: 8 additions & 9 deletions test/functional/apm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,9 @@ describe('APM', function () {
// Insert test documents
return db
.collection('apm_test_2')
.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }], { w: 1 });
.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }], {
writeConcern: { w: 1 }
});
})
.then(r => {
expect(r.insertedCount).to.equal(6);
Expand Down Expand Up @@ -529,7 +531,9 @@ describe('APM', function () {
.then(() =>
db
.collection('apm_test_2')
.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }], { w: 1 })
.insertMany([{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }], {
writeConcern: { w: 1 }
})
)
.then(r => {
expect(r.insertedCount).to.equal(6);
Expand Down Expand Up @@ -961,13 +965,8 @@ describe('APM', function () {
if (args.requests) params.push(args.requests);

if (args.writeConcern) {
if (options == null) {
options = args.writeConcern;
} else {
for (let name in args.writeConcern) {
options[name] = args.writeConcern[name];
}
}
options = options || {};
options.writeConcern = args.writeConcern;
}

if (typeof args.ordered === 'boolean') {
Expand Down
Loading