diff --git a/src/db.ts b/src/db.ts index c6bf522d73..cba0239680 100644 --- a/src/db.ts +++ b/src/db.ts @@ -26,6 +26,7 @@ import AggregateOperation = require('./operations/aggregate'); import AddUserOperation = require('./operations/add_user'); import CollectionsOperation = require('./operations/collections'); import CommandOperation = require('./operations/command'); +import RunCommandOperation = require('./operations/run_command'); import CreateCollectionOperation = require('./operations/create_collection'); import CreateIndexesOperation = require('./operations/create_indexes'); import { DropCollectionOperation, DropDatabaseOperation } from './operations/drop'; @@ -241,7 +242,7 @@ class Db { if (typeof options === 'function') (callback = options), (options = {}); options = Object.assign({}, options); - const commandOperation = new CommandOperation(this, options, null, command); + const commandOperation = new RunCommandOperation(this, command, options); return executeOperation(this.s.topology, commandOperation, callback); } diff --git a/src/operations/command_v2.ts b/src/operations/command_v2.ts index f7d7e8bb5d..29945a688c 100644 --- a/src/operations/command_v2.ts +++ b/src/operations/command_v2.ts @@ -27,9 +27,10 @@ class CommandOperationV2 extends OperationBase { super(options); this.ns = parent.s.namespace.withCollection('$cmd'); - this.readPreference = ReadPreference.resolve(parent, this.options); - this.readConcern = resolveReadConcern(parent, this.options); - this.writeConcern = resolveWriteConcern(parent, this.options); + const propertyProvider = this.hasAspect(Aspect.NO_INHERIT_OPTIONS) ? undefined : parent; + this.readPreference = ReadPreference.resolve(propertyProvider, this.options); + this.readConcern = resolveReadConcern(propertyProvider, this.options); + this.writeConcern = resolveWriteConcern(propertyProvider, this.options); this.explain = false; if (operationOptions && typeof operationOptions.fullResponse === 'boolean') { @@ -108,11 +109,11 @@ class CommandOperationV2 extends OperationBase { } function resolveWriteConcern(parent: any, options: any) { - return WriteConcern.fromOptions(options) || parent.writeConcern; + return WriteConcern.fromOptions(options) || (parent && parent.writeConcern); } function resolveReadConcern(parent: any, options: any) { - return ReadConcern.fromOptions(options) || parent.readConcern; + return ReadConcern.fromOptions(options) || (parent && parent.readConcern); } export = CommandOperationV2; diff --git a/src/operations/operation.ts b/src/operations/operation.ts index c378dd2c62..1dbff45670 100644 --- a/src/operations/operation.ts +++ b/src/operations/operation.ts @@ -2,7 +2,8 @@ const Aspect = { READ_OPERATION: Symbol('READ_OPERATION'), WRITE_OPERATION: Symbol('WRITE_OPERATION'), RETRYABLE: Symbol('RETRYABLE'), - EXECUTE_WITH_SELECTION: Symbol('EXECUTE_WITH_SELECTION') + EXECUTE_WITH_SELECTION: Symbol('EXECUTE_WITH_SELECTION'), + NO_INHERIT_OPTIONS: Symbol('NO_INHERIT_OPTIONS') }; /** diff --git a/src/operations/run_command.ts b/src/operations/run_command.ts new file mode 100644 index 0000000000..7180796e88 --- /dev/null +++ b/src/operations/run_command.ts @@ -0,0 +1,21 @@ +import CommandOperationV2 = require('./command_v2'); +import { defineAspects, Aspect } from './operation'; +import Db = require('../db'); +import Collection = require('../collection'); +import MongoClient = require('../mongo_client'); +import { Server } from '../sdam/server'; + +class RunCommandOperation extends CommandOperationV2 { + command: any; + constructor(parent: MongoClient | Db | Collection, command: any, options: any) { + super(parent, options); + this.command = command; + } + execute(server: Server, callback: any) { + const command = this.command; + this.executeCommand(server, command, callback); + } +} +defineAspects(RunCommandOperation, [Aspect.EXECUTE_WITH_SELECTION, Aspect.NO_INHERIT_OPTIONS]); + +export = RunCommandOperation; diff --git a/src/read_preference.ts b/src/read_preference.ts index d01e569883..2da85e1051 100644 --- a/src/read_preference.ts +++ b/src/read_preference.ts @@ -127,7 +127,7 @@ class ReadPreference { options = options || {}; const session = options.session; - const inheritedReadPreference = parent.readPreference; + const inheritedReadPreference = parent && parent.readPreference; let readPreference; if (options.readPreference) { @@ -138,7 +138,7 @@ class ReadPreference { } else if (inheritedReadPreference != null) { readPreference = inheritedReadPreference; } else { - throw new Error('No readPreference was provided or inherited.'); + readPreference = ReadPreference.primary; } return typeof readPreference === 'string' ? new ReadPreference(readPreference) : readPreference; @@ -148,12 +148,22 @@ class ReadPreference { * Replaces options.readPreference with a ReadPreference instance */ static translate(options: any) { - if (options.readPreference == null) return undefined; + if (options.readPreference == null) return options; const r = options.readPreference; - options.readPreference = ReadPreference.fromOptions(options); - if (!(options.readPreference instanceof ReadPreference)) { + + if (typeof r === 'string') { + options.readPreference = new ReadPreference(r); + } else if (r && !(r instanceof ReadPreference) && typeof r === 'object') { + const mode = r.mode || r.preference; + if (mode && typeof mode === 'string') { + options.readPreference = new ReadPreference(mode, r.tags, { + maxStalenessSeconds: r.maxStalenessSeconds + }); + } + } else if (!(r instanceof ReadPreference)) { throw new TypeError('Invalid read preference: ' + r); } + return options; }