mirror of
https://github.com/bvanroll/yahoo-thing.git
synced 2025-08-30 04:22:42 +00:00
euh
This commit is contained in:
666
node_modules/mongodb-core/lib/sdam/topology.js
generated
vendored
Normal file
666
node_modules/mongodb-core/lib/sdam/topology.js
generated
vendored
Normal file
@@ -0,0 +1,666 @@
|
||||
'use strict';
|
||||
const EventEmitter = require('events');
|
||||
const ServerDescription = require('./server_description').ServerDescription;
|
||||
const TopologyDescription = require('./topology_description').TopologyDescription;
|
||||
const TopologyType = require('./topology_description').TopologyType;
|
||||
const monitoring = require('./monitoring');
|
||||
const calculateDurationInMs = require('../utils').calculateDurationInMs;
|
||||
const MongoTimeoutError = require('../error').MongoTimeoutError;
|
||||
const MongoNetworkError = require('../error').MongoNetworkError;
|
||||
const Server = require('./server');
|
||||
const relayEvents = require('../utils').relayEvents;
|
||||
const ReadPreference = require('../topologies/read_preference');
|
||||
const readPreferenceServerSelector = require('./server_selectors').readPreferenceServerSelector;
|
||||
const writableServerSelector = require('./server_selectors').writableServerSelector;
|
||||
const isRetryableWritesSupported = require('../topologies/shared').isRetryableWritesSupported;
|
||||
const Cursor = require('./cursor');
|
||||
const deprecate = require('util').deprecate;
|
||||
const BSON = require('../connection/utils').retrieveBSON();
|
||||
const createCompressionInfo = require('../topologies/shared').createCompressionInfo;
|
||||
|
||||
// Global state
|
||||
let globalTopologyCounter = 0;
|
||||
|
||||
// Constants
|
||||
const TOPOLOGY_DEFAULTS = {
|
||||
localThresholdMS: 15,
|
||||
serverSelectionTimeoutMS: 10000,
|
||||
heartbeatFrequencyMS: 30000,
|
||||
minHeartbeatIntervalMS: 500
|
||||
};
|
||||
|
||||
/**
|
||||
* A container of server instances representing a connection to a MongoDB topology.
|
||||
*
|
||||
* @fires Topology#serverOpening
|
||||
* @fires Topology#serverClosed
|
||||
* @fires Topology#serverDescriptionChanged
|
||||
* @fires Topology#topologyOpening
|
||||
* @fires Topology#topologyClosed
|
||||
* @fires Topology#topologyDescriptionChanged
|
||||
* @fires Topology#serverHeartbeatStarted
|
||||
* @fires Topology#serverHeartbeatSucceeded
|
||||
* @fires Topology#serverHeartbeatFailed
|
||||
*/
|
||||
class Topology extends EventEmitter {
|
||||
/**
|
||||
* Create a topology
|
||||
*
|
||||
* @param {Array|String} [seedlist] a string list, or array of Server instances to connect to
|
||||
* @param {Object} [options] Optional settings
|
||||
* @param {Number} [options.localThresholdMS=15] The size of the latency window for selecting among multiple suitable servers
|
||||
* @param {Number} [options.serverSelectionTimeoutMS=30000] How long to block for server selection before throwing an error
|
||||
* @param {Number} [options.heartbeatFrequencyMS=10000] The frequency with which topology updates are scheduled
|
||||
*/
|
||||
constructor(seedlist, options) {
|
||||
super();
|
||||
if (typeof options === 'undefined') {
|
||||
options = seedlist;
|
||||
seedlist = [];
|
||||
|
||||
// this is for legacy single server constructor support
|
||||
if (options.host) {
|
||||
seedlist.push({ host: options.host, port: options.port });
|
||||
}
|
||||
}
|
||||
|
||||
seedlist = seedlist || [];
|
||||
options = Object.assign({}, TOPOLOGY_DEFAULTS, options);
|
||||
|
||||
const topologyType = topologyTypeFromSeedlist(seedlist, options);
|
||||
const topologyId = globalTopologyCounter++;
|
||||
const serverDescriptions = seedlist.reduce((result, seed) => {
|
||||
const address = seed.port ? `${seed.host}:${seed.port}` : `${seed.host}:27017`;
|
||||
result.set(address, new ServerDescription(address));
|
||||
return result;
|
||||
}, new Map());
|
||||
|
||||
this.s = {
|
||||
// the id of this topology
|
||||
id: topologyId,
|
||||
// passed in options
|
||||
options: Object.assign({}, options),
|
||||
// initial seedlist of servers to connect to
|
||||
seedlist: seedlist,
|
||||
// the topology description
|
||||
description: new TopologyDescription(
|
||||
topologyType,
|
||||
serverDescriptions,
|
||||
options.replicaSet,
|
||||
null,
|
||||
null,
|
||||
options
|
||||
),
|
||||
serverSelectionTimeoutMS: options.serverSelectionTimeoutMS,
|
||||
heartbeatFrequencyMS: options.heartbeatFrequencyMS,
|
||||
minHeartbeatIntervalMS: options.minHeartbeatIntervalMS,
|
||||
// allow users to override the cursor factory
|
||||
Cursor: options.cursorFactory || Cursor,
|
||||
// the bson parser
|
||||
bson:
|
||||
options.bson ||
|
||||
new BSON([
|
||||
BSON.Binary,
|
||||
BSON.Code,
|
||||
BSON.DBRef,
|
||||
BSON.Decimal128,
|
||||
BSON.Double,
|
||||
BSON.Int32,
|
||||
BSON.Long,
|
||||
BSON.Map,
|
||||
BSON.MaxKey,
|
||||
BSON.MinKey,
|
||||
BSON.ObjectId,
|
||||
BSON.BSONRegExp,
|
||||
BSON.Symbol,
|
||||
BSON.Timestamp
|
||||
])
|
||||
};
|
||||
|
||||
// amend options for server instance creation
|
||||
this.s.options.compression = { compressors: createCompressionInfo(options) };
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A `TopologyDescription` for this topology
|
||||
*/
|
||||
get description() {
|
||||
return this.s.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* All raw connections
|
||||
* @method
|
||||
* @return {Connection[]}
|
||||
*/
|
||||
connections() {
|
||||
return Array.from(this.s.servers.values()).reduce((result, server) => {
|
||||
return result.concat(server.s.pool.allConnections());
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate server connect
|
||||
*
|
||||
* @param {Object} [options] Optional settings
|
||||
* @param {Array} [options.auth=null] Array of auth options to apply on connect
|
||||
*/
|
||||
connect(/* options */) {
|
||||
// emit SDAM monitoring events
|
||||
this.emit('topologyOpening', new monitoring.TopologyOpeningEvent(this.s.id));
|
||||
|
||||
// emit an event for the topology change
|
||||
this.emit(
|
||||
'topologyDescriptionChanged',
|
||||
new monitoring.TopologyDescriptionChangedEvent(
|
||||
this.s.id,
|
||||
new TopologyDescription(TopologyType.Unknown), // initial is always Unknown
|
||||
this.s.description
|
||||
)
|
||||
);
|
||||
|
||||
connectServers(this, Array.from(this.s.description.servers.values()));
|
||||
this.s.connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this topology
|
||||
*/
|
||||
close(callback) {
|
||||
// destroy all child servers
|
||||
this.s.servers.forEach(server => server.destroy());
|
||||
|
||||
// emit an event for close
|
||||
this.emit('topologyClosed', new monitoring.TopologyClosedEvent(this.s.id));
|
||||
|
||||
this.s.connected = false;
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a server according to the selection predicate provided
|
||||
*
|
||||
* @param {function} [selector] An optional selector to select servers by, defaults to a random selection within a latency window
|
||||
* @return {Server} An instance of a `Server` meeting the criteria of the predicate provided
|
||||
*/
|
||||
selectServer(selector, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = Object.assign(
|
||||
{},
|
||||
{ serverSelectionTimeoutMS: this.s.serverSelectionTimeoutMS },
|
||||
options
|
||||
);
|
||||
|
||||
selectServers(
|
||||
this,
|
||||
selector,
|
||||
options.serverSelectionTimeoutMS,
|
||||
process.hrtime(),
|
||||
(err, servers) => {
|
||||
if (err) return callback(err, null);
|
||||
callback(null, randomSelection(servers));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the internal TopologyDescription with a ServerDescription
|
||||
*
|
||||
* @param {object} serverDescription The server to update in the internal list of server descriptions
|
||||
*/
|
||||
serverUpdateHandler(serverDescription) {
|
||||
if (!this.s.description.hasServer(serverDescription.address)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// these will be used for monitoring events later
|
||||
const previousTopologyDescription = this.s.description;
|
||||
const previousServerDescription = this.s.description.servers.get(serverDescription.address);
|
||||
|
||||
// first update the TopologyDescription
|
||||
this.s.description = this.s.description.update(serverDescription);
|
||||
|
||||
// emit monitoring events for this change
|
||||
this.emit(
|
||||
'serverDescriptionChanged',
|
||||
new monitoring.ServerDescriptionChangedEvent(
|
||||
this.s.id,
|
||||
serverDescription.address,
|
||||
previousServerDescription,
|
||||
this.s.description.servers.get(serverDescription.address)
|
||||
)
|
||||
);
|
||||
|
||||
// update server list from updated descriptions
|
||||
updateServers(this, serverDescription);
|
||||
|
||||
this.emit(
|
||||
'topologyDescriptionChanged',
|
||||
new monitoring.TopologyDescriptionChangedEvent(
|
||||
this.s.id,
|
||||
previousTopologyDescription,
|
||||
this.s.description
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate using a specified mechanism
|
||||
*
|
||||
* @param {String} mechanism The auth mechanism used for authentication
|
||||
* @param {String} db The db we are authenticating against
|
||||
* @param {Object} options Optional settings for the authenticating mechanism
|
||||
* @param {authResultCallback} callback A callback function
|
||||
*/
|
||||
auth(mechanism, db, options, callback) {
|
||||
callback(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout from a database
|
||||
*
|
||||
* @param {String} db The db we are logging out from
|
||||
* @param {authResultCallback} callback A callback function
|
||||
*/
|
||||
logout(db, callback) {
|
||||
callback(null, null);
|
||||
}
|
||||
|
||||
// Basic operation support. Eventually this should be moved into command construction
|
||||
// during the command refactor.
|
||||
|
||||
/**
|
||||
* Insert one or more documents
|
||||
*
|
||||
* @param {String} ns The full qualified namespace for this operation
|
||||
* @param {Array} ops An array of documents to insert
|
||||
* @param {Boolean} [options.ordered=true] Execute in order or out of order
|
||||
* @param {Object} [options.writeConcern] Write concern for the operation
|
||||
* @param {Boolean} [options.serializeFunctions=false] Specify if functions on an object should be serialized
|
||||
* @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields
|
||||
* @param {ClientSession} [options.session] Session to use for the operation
|
||||
* @param {boolean} [options.retryWrites] Enable retryable writes for this operation
|
||||
* @param {opResultCallback} callback A callback function
|
||||
*/
|
||||
insert(ns, ops, options, callback) {
|
||||
executeWriteOperation({ topology: this, op: 'insert', ns, ops }, options, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform one or more update operations
|
||||
*
|
||||
* @param {string} ns The fully qualified namespace for this operation
|
||||
* @param {array} ops An array of updates
|
||||
* @param {boolean} [options.ordered=true] Execute in order or out of order
|
||||
* @param {object} [options.writeConcern] Write concern for the operation
|
||||
* @param {Boolean} [options.serializeFunctions=false] Specify if functions on an object should be serialized
|
||||
* @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields
|
||||
* @param {ClientSession} [options.session] Session to use for the operation
|
||||
* @param {boolean} [options.retryWrites] Enable retryable writes for this operation
|
||||
* @param {opResultCallback} callback A callback function
|
||||
*/
|
||||
update(ns, ops, options, callback) {
|
||||
executeWriteOperation({ topology: this, op: 'update', ns, ops }, options, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform one or more remove operations
|
||||
*
|
||||
* @param {string} ns The MongoDB fully qualified namespace (ex: db1.collection1)
|
||||
* @param {array} ops An array of removes
|
||||
* @param {boolean} [options.ordered=true] Execute in order or out of order
|
||||
* @param {object} [options.writeConcern={}] Write concern for the operation
|
||||
* @param {Boolean} [options.serializeFunctions=false] Specify if functions on an object should be serialized.
|
||||
* @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
||||
* @param {ClientSession} [options.session=null] Session to use for the operation
|
||||
* @param {boolean} [options.retryWrites] Enable retryable writes for this operation
|
||||
* @param {opResultCallback} callback A callback function
|
||||
*/
|
||||
remove(ns, ops, options, callback) {
|
||||
executeWriteOperation({ topology: this, op: 'remove', ns, ops }, options, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command
|
||||
*
|
||||
* @method
|
||||
* @param {string} ns The MongoDB fully qualified namespace (ex: db1.collection1)
|
||||
* @param {object} cmd The command hash
|
||||
* @param {ReadPreference} [options.readPreference] Specify read preference if command supports it
|
||||
* @param {Connection} [options.connection] Specify connection object to execute command against
|
||||
* @param {Boolean} [options.serializeFunctions=false] Specify if functions on an object should be serialized.
|
||||
* @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
||||
* @param {ClientSession} [options.session=null] Session to use for the operation
|
||||
* @param {opResultCallback} callback A callback function
|
||||
*/
|
||||
command(ns, cmd, options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
(callback = options), (options = {}), (options = options || {});
|
||||
}
|
||||
|
||||
const readPreference = options.readPreference ? options.readPreference : ReadPreference.primary;
|
||||
this.selectServer(readPreferenceServerSelector(readPreference), (err, server) => {
|
||||
if (err) {
|
||||
callback(err, null);
|
||||
return;
|
||||
}
|
||||
|
||||
server.command(ns, cmd, options, callback);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new cursor
|
||||
*
|
||||
* @method
|
||||
* @param {string} ns The MongoDB fully qualified namespace (ex: db1.collection1)
|
||||
* @param {object|Long} cmd Can be either a command returning a cursor or a cursorId
|
||||
* @param {object} [options] Options for the cursor
|
||||
* @param {object} [options.batchSize=0] Batchsize for the operation
|
||||
* @param {array} [options.documents=[]] Initial documents list for cursor
|
||||
* @param {ReadPreference} [options.readPreference] Specify read preference if command supports it
|
||||
* @param {Boolean} [options.serializeFunctions=false] Specify if functions on an object should be serialized.
|
||||
* @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
|
||||
* @param {ClientSession} [options.session=null] Session to use for the operation
|
||||
* @param {object} [options.topology] The internal topology of the created cursor
|
||||
* @returns {Cursor}
|
||||
*/
|
||||
cursor(ns, cmd, options) {
|
||||
options = options || {};
|
||||
const topology = options.topology || this;
|
||||
const CursorClass = options.cursorFactory || this.s.Cursor;
|
||||
|
||||
return new CursorClass(this.s.bson, ns, cmd, options, topology, this.s.options);
|
||||
}
|
||||
}
|
||||
|
||||
// legacy aliases
|
||||
Topology.prototype.destroy = deprecate(
|
||||
Topology.prototype.close,
|
||||
'destroy() is deprecated, please use close() instead'
|
||||
);
|
||||
|
||||
function topologyTypeFromSeedlist(seedlist, options) {
|
||||
if (seedlist.length === 1 && !options.replicaSet) return TopologyType.Single;
|
||||
if (options.replicaSet) return TopologyType.ReplicaSetNoPrimary;
|
||||
return TopologyType.Unknown;
|
||||
}
|
||||
|
||||
function randomSelection(array) {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects servers using the provided selector
|
||||
*
|
||||
* @private
|
||||
* @param {Topology} topology The topology to select servers from
|
||||
* @param {function} selector The actual predicate used for selecting servers
|
||||
* @param {Number} timeout The max time we are willing wait for selection
|
||||
* @param {Number} start A high precision timestamp for the start of the selection process
|
||||
* @param {function} callback The callback used to convey errors or the resultant servers
|
||||
*/
|
||||
function selectServers(topology, selector, timeout, start, callback) {
|
||||
const serverDescriptions = Array.from(topology.description.servers.values());
|
||||
let descriptions;
|
||||
|
||||
try {
|
||||
descriptions = selector
|
||||
? selector(topology.description, serverDescriptions)
|
||||
: serverDescriptions;
|
||||
} catch (e) {
|
||||
return callback(e, null);
|
||||
}
|
||||
|
||||
if (descriptions.length) {
|
||||
const servers = descriptions.map(description => topology.s.servers.get(description.address));
|
||||
return callback(null, servers);
|
||||
}
|
||||
|
||||
const duration = calculateDurationInMs(start);
|
||||
if (duration >= timeout) {
|
||||
return callback(new MongoTimeoutError(`Server selection timed out after ${timeout} ms`));
|
||||
}
|
||||
|
||||
const retrySelection = () => {
|
||||
// ensure all server monitors attempt monitoring immediately
|
||||
topology.s.servers.forEach(server => server.monitor());
|
||||
|
||||
const iterationTimer = setTimeout(() => {
|
||||
callback(new MongoTimeoutError('Server selection timed out due to monitoring'));
|
||||
}, topology.s.minHeartbeatIntervalMS);
|
||||
|
||||
topology.once('topologyDescriptionChanged', () => {
|
||||
// successful iteration, clear the check timer
|
||||
clearTimeout(iterationTimer);
|
||||
|
||||
// topology description has changed due to monitoring, reattempt server selection
|
||||
selectServers(topology, selector, timeout, start, callback);
|
||||
});
|
||||
};
|
||||
|
||||
// ensure we are connected
|
||||
if (!topology.s.connected) {
|
||||
topology.connect();
|
||||
|
||||
// we want to make sure we're still within the requested timeout window
|
||||
const failToConnectTimer = setTimeout(() => {
|
||||
callback(new MongoTimeoutError('Server selection timed out waiting to connect'));
|
||||
}, timeout - duration);
|
||||
|
||||
topology.once('connect', () => {
|
||||
clearTimeout(failToConnectTimer);
|
||||
retrySelection();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
retrySelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create `Server` instances for all initially known servers, connect them, and assign
|
||||
* them to the passed in `Topology`.
|
||||
*
|
||||
* @param {Topology} topology The topology responsible for the servers
|
||||
* @param {ServerDescription[]} serverDescriptions A list of server descriptions to connect
|
||||
*/
|
||||
function connectServers(topology, serverDescriptions) {
|
||||
topology.s.servers = serverDescriptions.reduce((servers, serverDescription) => {
|
||||
// publish an open event for each ServerDescription created
|
||||
topology.emit(
|
||||
'serverOpening',
|
||||
new monitoring.ServerOpeningEvent(topology.s.id, serverDescription.address)
|
||||
);
|
||||
|
||||
const server = new Server(serverDescription, topology.s.options);
|
||||
relayEvents(server, topology, [
|
||||
'serverHeartbeatStarted',
|
||||
'serverHeartbeatSucceeded',
|
||||
'serverHeartbeatFailed'
|
||||
]);
|
||||
|
||||
server.on('descriptionReceived', topology.serverUpdateHandler.bind(topology));
|
||||
server.on('connect', serverConnectEventHandler(server, topology));
|
||||
servers.set(serverDescription.address, server);
|
||||
server.connect();
|
||||
return servers;
|
||||
}, new Map());
|
||||
}
|
||||
|
||||
function updateServers(topology, currentServerDescription) {
|
||||
// update the internal server's description
|
||||
if (topology.s.servers.has(currentServerDescription.address)) {
|
||||
const server = topology.s.servers.get(currentServerDescription.address);
|
||||
server.s.description = currentServerDescription;
|
||||
}
|
||||
|
||||
// add new servers for all descriptions we currently don't know about locally
|
||||
for (const serverDescription of topology.description.servers.values()) {
|
||||
if (!topology.s.servers.has(serverDescription.address)) {
|
||||
topology.emit(
|
||||
'serverOpening',
|
||||
new monitoring.ServerOpeningEvent(topology.s.id, serverDescription.address)
|
||||
);
|
||||
|
||||
const server = new Server(serverDescription, topology.s.options);
|
||||
relayEvents(server, topology, [
|
||||
'serverHeartbeatStarted',
|
||||
'serverHeartbeatSucceeded',
|
||||
'serverHeartbeatFailed'
|
||||
]);
|
||||
|
||||
server.on('descriptionReceived', topology.serverUpdateHandler.bind(topology));
|
||||
server.on('connect', serverConnectEventHandler(server, topology));
|
||||
topology.s.servers.set(serverDescription.address, server);
|
||||
server.connect();
|
||||
}
|
||||
}
|
||||
|
||||
// for all servers no longer known, remove their descriptions and destroy their instances
|
||||
for (const entry of topology.s.servers) {
|
||||
const serverAddress = entry[0];
|
||||
if (topology.description.hasServer(serverAddress)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const server = topology.s.servers.get(serverAddress);
|
||||
topology.s.servers.delete(serverAddress);
|
||||
|
||||
server.destroy(() =>
|
||||
topology.emit('serverClosed', new monitoring.ServerClosedEvent(topology.s.id, serverAddress))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function serverConnectEventHandler(server, topology) {
|
||||
return function(/* ismaster */) {
|
||||
topology.emit('connect', topology);
|
||||
};
|
||||
}
|
||||
|
||||
function executeWriteOperation(args, options, callback) {
|
||||
if (typeof options === 'function') (callback = options), (options = {});
|
||||
options = options || {};
|
||||
|
||||
// TODO: once we drop Node 4, use destructuring either here or in arguments.
|
||||
const topology = args.topology;
|
||||
const op = args.op;
|
||||
const ns = args.ns;
|
||||
const ops = args.ops;
|
||||
|
||||
const willRetryWrite =
|
||||
!args.retrying &&
|
||||
options.retryWrites &&
|
||||
options.session &&
|
||||
isRetryableWritesSupported(topology) &&
|
||||
!options.session.inTransaction();
|
||||
|
||||
topology.selectServer(writableServerSelector(), (err, server) => {
|
||||
if (err) {
|
||||
callback(err, null);
|
||||
return;
|
||||
}
|
||||
|
||||
const handler = (err, result) => {
|
||||
if (!err) return callback(null, result);
|
||||
if (!(err instanceof MongoNetworkError) && !err.message.match(/not master/)) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (willRetryWrite) {
|
||||
const newArgs = Object.assign({}, args, { retrying: true });
|
||||
return executeWriteOperation(newArgs, options, callback);
|
||||
}
|
||||
|
||||
return callback(err);
|
||||
};
|
||||
|
||||
if (callback.operationId) {
|
||||
handler.operationId = callback.operationId;
|
||||
}
|
||||
|
||||
// increment and assign txnNumber
|
||||
if (willRetryWrite) {
|
||||
options.session.incrementTransactionNumber();
|
||||
options.willRetryWrite = willRetryWrite;
|
||||
}
|
||||
|
||||
// execute the write operation
|
||||
server[op](ns, ops, options, handler);
|
||||
|
||||
// we need to increment the statement id if we're in a transaction
|
||||
if (options.session && options.session.inTransaction()) {
|
||||
options.session.incrementStatementId(ops.length);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A server opening SDAM monitoring event
|
||||
*
|
||||
* @event Topology#serverOpening
|
||||
* @type {ServerOpeningEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A server closed SDAM monitoring event
|
||||
*
|
||||
* @event Topology#serverClosed
|
||||
* @type {ServerClosedEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A server description SDAM change monitoring event
|
||||
*
|
||||
* @event Topology#serverDescriptionChanged
|
||||
* @type {ServerDescriptionChangedEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A topology open SDAM event
|
||||
*
|
||||
* @event Topology#topologyOpening
|
||||
* @type {TopologyOpeningEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A topology closed SDAM event
|
||||
*
|
||||
* @event Topology#topologyClosed
|
||||
* @type {TopologyClosedEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A topology structure SDAM change event
|
||||
*
|
||||
* @event Topology#topologyDescriptionChanged
|
||||
* @type {TopologyDescriptionChangedEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A topology serverHeartbeatStarted SDAM event
|
||||
*
|
||||
* @event Topology#serverHeartbeatStarted
|
||||
* @type {ServerHeartbeatStartedEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A topology serverHeartbeatFailed SDAM event
|
||||
*
|
||||
* @event Topology#serverHeartbeatFailed
|
||||
* @type {ServerHearbeatFailedEvent}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A topology serverHeartbeatSucceeded SDAM change event
|
||||
*
|
||||
* @event Topology#serverHeartbeatSucceeded
|
||||
* @type {ServerHeartbeatSucceededEvent}
|
||||
*/
|
||||
|
||||
module.exports = Topology;
|
Reference in New Issue
Block a user