Skip to content

Commit 8f6c247

Browse files
author
Thomas Reggi
authored
fix: db.command to not inherit options from parent
Fixes `db.command` method to not inherit readPreference, writeConcern, readConcern from parent. centralizes readPreference helpers translate, resolve, fromOptions to the ReadPreference class. Adds Aspect "NO_INHERIT_OPTIONS" to command operations for flagging specific operations. Creates `RunCommand` operation to wrap `CommandV2`, updating `db.command` to use `CommandV2`. NODE-2649
1 parent eff550d commit 8f6c247

File tree

5 files changed

+46
-12
lines changed

5 files changed

+46
-12
lines changed

src/db.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import AggregateOperation = require('./operations/aggregate');
2626
import AddUserOperation = require('./operations/add_user');
2727
import CollectionsOperation = require('./operations/collections');
2828
import CommandOperation = require('./operations/command');
29+
import RunCommandOperation = require('./operations/run_command');
2930
import CreateCollectionOperation = require('./operations/create_collection');
3031
import CreateIndexesOperation = require('./operations/create_indexes');
3132
import { DropCollectionOperation, DropDatabaseOperation } from './operations/drop';
@@ -241,7 +242,7 @@ class Db {
241242
if (typeof options === 'function') (callback = options), (options = {});
242243
options = Object.assign({}, options);
243244

244-
const commandOperation = new CommandOperation(this, options, null, command);
245+
const commandOperation = new RunCommandOperation(this, command, options);
245246

246247
return executeOperation(this.s.topology, commandOperation, callback);
247248
}

src/operations/command_v2.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ class CommandOperationV2 extends OperationBase {
2727
super(options);
2828

2929
this.ns = parent.s.namespace.withCollection('$cmd');
30-
this.readPreference = ReadPreference.resolve(parent, this.options);
31-
this.readConcern = resolveReadConcern(parent, this.options);
32-
this.writeConcern = resolveWriteConcern(parent, this.options);
30+
const propertyProvider = this.hasAspect(Aspect.NO_INHERIT_OPTIONS) ? undefined : parent;
31+
this.readPreference = ReadPreference.resolve(propertyProvider, this.options);
32+
this.readConcern = resolveReadConcern(propertyProvider, this.options);
33+
this.writeConcern = resolveWriteConcern(propertyProvider, this.options);
3334
this.explain = false;
3435

3536
if (operationOptions && typeof operationOptions.fullResponse === 'boolean') {
@@ -108,11 +109,11 @@ class CommandOperationV2 extends OperationBase {
108109
}
109110

110111
function resolveWriteConcern(parent: any, options: any) {
111-
return WriteConcern.fromOptions(options) || parent.writeConcern;
112+
return WriteConcern.fromOptions(options) || (parent && parent.writeConcern);
112113
}
113114

114115
function resolveReadConcern(parent: any, options: any) {
115-
return ReadConcern.fromOptions(options) || parent.readConcern;
116+
return ReadConcern.fromOptions(options) || (parent && parent.readConcern);
116117
}
117118

118119
export = CommandOperationV2;

src/operations/operation.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ const Aspect = {
22
READ_OPERATION: Symbol('READ_OPERATION'),
33
WRITE_OPERATION: Symbol('WRITE_OPERATION'),
44
RETRYABLE: Symbol('RETRYABLE'),
5-
EXECUTE_WITH_SELECTION: Symbol('EXECUTE_WITH_SELECTION')
5+
EXECUTE_WITH_SELECTION: Symbol('EXECUTE_WITH_SELECTION'),
6+
NO_INHERIT_OPTIONS: Symbol('NO_INHERIT_OPTIONS')
67
};
78

89
/**

src/operations/run_command.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import CommandOperationV2 = require('./command_v2');
2+
import { defineAspects, Aspect } from './operation';
3+
import Db = require('../db');
4+
import Collection = require('../collection');
5+
import MongoClient = require('../mongo_client');
6+
import { Server } from '../sdam/server';
7+
8+
class RunCommandOperation extends CommandOperationV2 {
9+
command: any;
10+
constructor(parent: MongoClient | Db | Collection, command: any, options: any) {
11+
super(parent, options);
12+
this.command = command;
13+
}
14+
execute(server: Server, callback: any) {
15+
const command = this.command;
16+
this.executeCommand(server, command, callback);
17+
}
18+
}
19+
defineAspects(RunCommandOperation, [Aspect.EXECUTE_WITH_SELECTION, Aspect.NO_INHERIT_OPTIONS]);
20+
21+
export = RunCommandOperation;

src/read_preference.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class ReadPreference {
127127
options = options || {};
128128
const session = options.session;
129129

130-
const inheritedReadPreference = parent.readPreference;
130+
const inheritedReadPreference = parent && parent.readPreference;
131131

132132
let readPreference;
133133
if (options.readPreference) {
@@ -138,7 +138,7 @@ class ReadPreference {
138138
} else if (inheritedReadPreference != null) {
139139
readPreference = inheritedReadPreference;
140140
} else {
141-
throw new Error('No readPreference was provided or inherited.');
141+
readPreference = ReadPreference.primary;
142142
}
143143

144144
return typeof readPreference === 'string' ? new ReadPreference(readPreference) : readPreference;
@@ -148,12 +148,22 @@ class ReadPreference {
148148
* Replaces options.readPreference with a ReadPreference instance
149149
*/
150150
static translate(options: any) {
151-
if (options.readPreference == null) return undefined;
151+
if (options.readPreference == null) return options;
152152
const r = options.readPreference;
153-
options.readPreference = ReadPreference.fromOptions(options);
154-
if (!(options.readPreference instanceof ReadPreference)) {
153+
154+
if (typeof r === 'string') {
155+
options.readPreference = new ReadPreference(r);
156+
} else if (r && !(r instanceof ReadPreference) && typeof r === 'object') {
157+
const mode = r.mode || r.preference;
158+
if (mode && typeof mode === 'string') {
159+
options.readPreference = new ReadPreference(mode, r.tags, {
160+
maxStalenessSeconds: r.maxStalenessSeconds
161+
});
162+
}
163+
} else if (!(r instanceof ReadPreference)) {
155164
throw new TypeError('Invalid read preference: ' + r);
156165
}
166+
157167
return options;
158168
}
159169

0 commit comments

Comments
 (0)