Skip to content

Commit 1f880ea

Browse files
authored
feat(NODE-5274): deprecate write concern options (#3752)
1 parent 0668cd8 commit 1f880ea

File tree

9 files changed

+215
-56
lines changed

9 files changed

+215
-56
lines changed

src/gridfs/upload.ts

+4-17
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,8 @@ async function checkChunksIndex(stream: GridFSBucketWriteStream): Promise<void>
263263
});
264264

265265
if (!hasChunksIndex) {
266-
const writeConcernOptions = getWriteOptions(stream);
267266
await stream.chunks.createIndex(index, {
268-
...writeConcernOptions,
267+
...stream.writeConcern,
269268
background: true,
270269
unique: true
271270
});
@@ -292,7 +291,7 @@ function checkDone(stream: GridFSBucketWriteStream, callback?: Callback): boolea
292291
return false;
293292
}
294293

295-
stream.files.insertOne(filesDoc, getWriteOptions(stream)).then(
294+
stream.files.insertOne(filesDoc, { writeConcern: stream.writeConcern }).then(
296295
() => {
297296
stream.emit(GridFSBucketWriteStream.FINISH, filesDoc);
298297
stream.emit(GridFSBucketWriteStream.CLOSE);
@@ -423,7 +422,7 @@ function doWrite(
423422
return false;
424423
}
425424

426-
stream.chunks.insertOne(doc, getWriteOptions(stream)).then(
425+
stream.chunks.insertOne(doc, { writeConcern: stream.writeConcern }).then(
427426
() => {
428427
--stream.state.outstandingRequests;
429428
--outstandingRequests;
@@ -453,18 +452,6 @@ function doWrite(
453452
return false;
454453
}
455454

456-
function getWriteOptions(stream: GridFSBucketWriteStream): WriteConcernOptions {
457-
const obj: WriteConcernOptions = {};
458-
if (stream.writeConcern) {
459-
obj.writeConcern = {
460-
w: stream.writeConcern.w,
461-
wtimeout: stream.writeConcern.wtimeout,
462-
j: stream.writeConcern.j
463-
};
464-
}
465-
return obj;
466-
}
467-
468455
function waitForIndexes(
469456
stream: GridFSBucketWriteStream,
470457
callback: (res: boolean) => boolean
@@ -499,7 +486,7 @@ function writeRemnant(stream: GridFSBucketWriteStream, callback?: Callback): boo
499486
return false;
500487
}
501488

502-
stream.chunks.insertOne(doc, getWriteOptions(stream)).then(
489+
stream.chunks.insertOne(doc, { writeConcern: stream.writeConcern }).then(
503490
() => {
504491
--stream.state.outstandingRequests;
505492
checkDone(stream);

src/operations/aggregate.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { MongoInvalidArgumentError } from '../error';
33
import type { Server } from '../sdam/server';
44
import type { ClientSession } from '../sessions';
55
import { type Callback, maxWireVersion, type MongoDBNamespace } from '../utils';
6+
import { WriteConcern } from '../write_concern';
67
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
78
import { Aspect, defineAspects, type Hint } from './operation';
89

@@ -102,7 +103,7 @@ export class AggregateOperation<T = Document> extends CommandOperation<T> {
102103
}
103104

104105
if (this.hasWriteStage && this.writeConcern) {
105-
Object.assign(command, { writeConcern: this.writeConcern });
106+
WriteConcern.apply(command, this.writeConcern);
106107
}
107108

108109
if (options.bypassDocumentValidation === true) {

src/operations/command.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export abstract class CommandOperation<T> extends AbstractCallbackOperation<T> {
135135
}
136136

137137
if (this.writeConcern && this.hasAspect(Aspect.WRITE_OPERATION) && !inTransaction) {
138-
Object.assign(cmd, { writeConcern: this.writeConcern });
138+
WriteConcern.apply(cmd, this.writeConcern);
139139
}
140140

141141
if (

src/sessions.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
now,
4646
uuidV4
4747
} from './utils';
48+
import { WriteConcern } from './write_concern';
4849

4950
const minWireVersionForShardedTransactions = 8;
5051

@@ -703,11 +704,11 @@ function endTransaction(
703704
}
704705

705706
if (txnState === TxnState.TRANSACTION_COMMITTED) {
706-
writeConcern = Object.assign({ wtimeout: 10000 }, writeConcern, { w: 'majority' });
707+
writeConcern = Object.assign({ wtimeoutMS: 10000 }, writeConcern, { w: 'majority' });
707708
}
708709

709710
if (writeConcern) {
710-
Object.assign(command, { writeConcern });
711+
WriteConcern.apply(command, writeConcern);
711712
}
712713

713714
if (commandName === 'commitTransaction' && session.transaction.options.maxTimeMS) {

src/write_concern.ts

+64-17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { type Document } from './bson';
2+
13
/** @public */
24
export type W = number | 'majority';
35

@@ -17,16 +19,35 @@ export interface WriteConcernSettings {
1719
journal?: boolean;
1820

1921
// legacy options
20-
/** The journal write concern */
22+
/**
23+
* The journal write concern.
24+
* @deprecated Will be removed in the next major version. Please use the journal option.
25+
*/
2126
j?: boolean;
22-
/** The write concern timeout */
27+
/**
28+
* The write concern timeout.
29+
* @deprecated Will be removed in the next major version. Please use the wtimeoutMS option.
30+
*/
2331
wtimeout?: number;
24-
/** The file sync write concern */
32+
/**
33+
* The file sync write concern.
34+
* @deprecated Will be removed in the next major version. Please use the journal option.
35+
*/
2536
fsync?: boolean | 1;
2637
}
2738

2839
export const WRITE_CONCERN_KEYS = ['w', 'wtimeout', 'j', 'journal', 'fsync'];
2940

41+
/** The write concern options that decorate the server command. */
42+
interface CommandWriteConcernOptions {
43+
/** The write concern */
44+
w?: W;
45+
/** The journal write concern. */
46+
j?: boolean;
47+
/** The write concern timeout. */
48+
wtimeout?: number;
49+
}
50+
3051
/**
3152
* A MongoDB WriteConcern, which describes the level of acknowledgement
3253
* requested from MongoDB for write operations.
@@ -35,41 +56,67 @@ export const WRITE_CONCERN_KEYS = ['w', 'wtimeout', 'j', 'journal', 'fsync'];
3556
* @see https://www.mongodb.com/docs/manual/reference/write-concern/
3657
*/
3758
export class WriteConcern {
38-
/** request acknowledgment that the write operation has propagated to a specified number of mongod instances or to mongod instances with specified tags. */
39-
w?: W;
40-
/** specify a time limit to prevent write operations from blocking indefinitely */
59+
/** Request acknowledgment that the write operation has propagated to a specified number of mongod instances or to mongod instances with specified tags. */
60+
readonly w?: W;
61+
/** Request acknowledgment that the write operation has been written to the on-disk journal */
62+
readonly journal?: boolean;
63+
/** Specify a time limit to prevent write operations from blocking indefinitely */
64+
readonly wtimeoutMS?: number;
65+
/**
66+
* Specify a time limit to prevent write operations from blocking indefinitely.
67+
* @deprecated Will be removed in the next major version. Please use wtimeoutMS.
68+
*/
4169
wtimeout?: number;
42-
/** request acknowledgment that the write operation has been written to the on-disk journal */
70+
/**
71+
* Request acknowledgment that the write operation has been written to the on-disk journal.
72+
* @deprecated Will be removed in the next major version. Please use journal.
73+
*/
4374
j?: boolean;
44-
/** equivalent to the j option */
75+
/**
76+
* Equivalent to the j option.
77+
* @deprecated Will be removed in the next major version. Please use journal.
78+
*/
4579
fsync?: boolean | 1;
4680

4781
/**
4882
* Constructs a WriteConcern from the write concern properties.
4983
* @param w - request acknowledgment that the write operation has propagated to a specified number of mongod instances or to mongod instances with specified tags.
50-
* @param wtimeout - specify a time limit to prevent write operations from blocking indefinitely
51-
* @param j - request acknowledgment that the write operation has been written to the on-disk journal
52-
* @param fsync - equivalent to the j option
84+
* @param wtimeoutMS - specify a time limit to prevent write operations from blocking indefinitely
85+
* @param journal - request acknowledgment that the write operation has been written to the on-disk journal
86+
* @param fsync - equivalent to the j option. Is deprecated and will be removed in the next major version.
5387
*/
54-
constructor(w?: W, wtimeout?: number, j?: boolean, fsync?: boolean | 1) {
88+
constructor(w?: W, wtimeoutMS?: number, journal?: boolean, fsync?: boolean | 1) {
5589
if (w != null) {
5690
if (!Number.isNaN(Number(w))) {
5791
this.w = Number(w);
5892
} else {
5993
this.w = w;
6094
}
6195
}
62-
if (wtimeout != null) {
63-
this.wtimeout = wtimeout;
96+
if (wtimeoutMS != null) {
97+
this.wtimeoutMS = this.wtimeout = wtimeoutMS;
6498
}
65-
if (j != null) {
66-
this.j = j;
99+
if (journal != null) {
100+
this.journal = this.j = journal;
67101
}
68102
if (fsync != null) {
69-
this.fsync = fsync;
103+
this.journal = this.j = fsync ? true : false;
70104
}
71105
}
72106

107+
/**
108+
* Apply a write concern to a command document. Will modify and return the command.
109+
*/
110+
static apply(command: Document, writeConcern: WriteConcern): Document {
111+
const wc: CommandWriteConcernOptions = {};
112+
// The write concern document sent to the server has w/wtimeout/j fields.
113+
if (writeConcern.w != null) wc.w = writeConcern.w;
114+
if (writeConcern.wtimeoutMS != null) wc.wtimeout = writeConcern.wtimeoutMS;
115+
if (writeConcern.journal != null) wc.j = writeConcern.j;
116+
command.writeConcern = wc;
117+
return command;
118+
}
119+
73120
/** Construct a WriteConcern given an options object. */
74121
static fromOptions(
75122
options?: WriteConcernOptions | WriteConcern | W,

test/integration/crud/find_and_modify.test.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -119,36 +119,36 @@ describe('Collection (#findOneAnd...)', function () {
119119
});
120120

121121
it('passes through the writeConcern', async function () {
122-
await collection.findOneAndDelete({}, { writeConcern: { fsync: 1 } });
123-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
122+
await collection.findOneAndDelete({}, { writeConcern: { j: 1 } });
123+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
124124
});
125125
});
126126

127127
context('when provided at the collection level', function () {
128128
beforeEach(async function () {
129129
collection = client
130130
.db('test')
131-
.collection('findAndModifyTest', { writeConcern: { fsync: 1 } });
131+
.collection('findAndModifyTest', { writeConcern: { j: 1 } });
132132
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
133133
});
134134

135135
it('passes through the writeConcern', async function () {
136136
await collection.findOneAndDelete({});
137-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
137+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
138138
});
139139
});
140140

141141
context('when provided at the db level', function () {
142142
beforeEach(async function () {
143143
collection = client
144-
.db('test', { writeConcern: { fsync: 1 } })
144+
.db('test', { writeConcern: { j: 1 } })
145145
.collection('findAndModifyTest');
146146
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
147147
});
148148

149149
it('passes through the writeConcern', async function () {
150150
await collection.findOneAndDelete({});
151-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
151+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
152152
});
153153
});
154154
});
@@ -297,36 +297,36 @@ describe('Collection (#findOneAnd...)', function () {
297297
});
298298

299299
it('passes through the writeConcern', async function () {
300-
await collection.findOneAndUpdate({}, { $set: { a: 1 } }, { writeConcern: { fsync: 1 } });
301-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
300+
await collection.findOneAndUpdate({}, { $set: { a: 1 } }, { writeConcern: { j: 1 } });
301+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
302302
});
303303
});
304304

305305
context('when provided at the collection level', function () {
306306
beforeEach(async function () {
307307
collection = client
308308
.db('test')
309-
.collection('findAndModifyTest', { writeConcern: { fsync: 1 } });
309+
.collection('findAndModifyTest', { writeConcern: { j: 1 } });
310310
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
311311
});
312312

313313
it('passes through the writeConcern', async function () {
314314
await collection.findOneAndUpdate({}, { $set: { a: 1 } });
315-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
315+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
316316
});
317317
});
318318

319319
context('when provided at the db level', function () {
320320
beforeEach(async function () {
321321
collection = client
322-
.db('test', { writeConcern: { fsync: 1 } })
322+
.db('test', { writeConcern: { j: 1 } })
323323
.collection('findAndModifyTest');
324324
await collection.insertMany([{ a: 1, b: 1 }], { writeConcern: { w: 1 } });
325325
});
326326

327327
it('passes through the writeConcern', async function () {
328328
await collection.findOneAndUpdate({}, { $set: { a: 1 } });
329-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
329+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
330330
});
331331
});
332332
});
@@ -468,8 +468,8 @@ describe('Collection (#findOneAnd...)', function () {
468468
});
469469

470470
it('passes through the writeConcern', async function () {
471-
await collection.findOneAndReplace({}, { b: 1 }, { writeConcern: { fsync: 1 } });
472-
expect(started[0].command.writeConcern).to.deep.equal({ fsync: 1 });
471+
await collection.findOneAndReplace({}, { b: 1 }, { writeConcern: { j: 1 } });
472+
expect(started[0].command.writeConcern).to.deep.equal({ j: 1 });
473473
});
474474
});
475475

test/integration/node-specific/mongo_client.test.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ describe('class MongoClient', function () {
5252

5353
expect(db).to.have.property('writeConcern');
5454
expect(db.writeConcern).to.have.property('w', 1);
55-
expect(db.writeConcern).to.have.property('wtimeout', 1000);
56-
expect(db.writeConcern).to.have.property('fsync', true);
57-
expect(db.writeConcern).to.have.property('j', true);
55+
expect(db.writeConcern).to.have.property('wtimeoutMS', 1000);
56+
expect(db.writeConcern).to.have.property('journal', true);
5857

5958
expect(db).to.have.property('s');
6059
expect(db.s).to.have.property('readPreference');

test/integration/uri-options/uri.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ describe('URI', function () {
6666
const client = this.configuration.newClient('mongodb://127.0.0.1:27017/?fsync=true');
6767
client.connect((err, client) => {
6868
var db = client.db(this.configuration.db);
69-
expect(db.writeConcern.fsync).to.be.true;
69+
expect(db.writeConcern.journal).to.be.true;
7070
client.close(done);
7171
});
7272
}

0 commit comments

Comments
 (0)