123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.compareTopologyVersion = exports.parseServerType = exports.ServerDescription = void 0;
- const bson_1 = require("../bson");
- const error_1 = require("../error");
- const utils_1 = require("../utils");
- const common_1 = require("./common");
- const WRITABLE_SERVER_TYPES = new Set([
- common_1.ServerType.RSPrimary,
- common_1.ServerType.Standalone,
- common_1.ServerType.Mongos,
- common_1.ServerType.LoadBalancer
- ]);
- const DATA_BEARING_SERVER_TYPES = new Set([
- common_1.ServerType.RSPrimary,
- common_1.ServerType.RSSecondary,
- common_1.ServerType.Mongos,
- common_1.ServerType.Standalone,
- common_1.ServerType.LoadBalancer
- ]);
- /**
- * The client's view of a single server, based on the most recent hello outcome.
- *
- * Internal type, not meant to be directly instantiated
- * @public
- */
- class ServerDescription {
- /**
- * Create a ServerDescription
- * @internal
- *
- * @param address - The address of the server
- * @param hello - An optional hello response for this server
- */
- constructor(address, hello, options = {}) {
- if (address == null || address === '') {
- throw new error_1.MongoRuntimeError('ServerDescription must be provided with a non-empty address');
- }
- this.address =
- typeof address === 'string'
- ? utils_1.HostAddress.fromString(address).toString() // Use HostAddress to normalize
- : address.toString();
- this.type = parseServerType(hello, options);
- this.hosts = hello?.hosts?.map((host) => host.toLowerCase()) ?? [];
- this.passives = hello?.passives?.map((host) => host.toLowerCase()) ?? [];
- this.arbiters = hello?.arbiters?.map((host) => host.toLowerCase()) ?? [];
- this.tags = hello?.tags ?? {};
- this.minWireVersion = hello?.minWireVersion ?? 0;
- this.maxWireVersion = hello?.maxWireVersion ?? 0;
- this.roundTripTime = options?.roundTripTime ?? -1;
- this.lastUpdateTime = (0, utils_1.now)();
- this.lastWriteDate = hello?.lastWrite?.lastWriteDate ?? 0;
- this.error = options.error ?? null;
- // TODO(NODE-2674): Preserve int64 sent from MongoDB
- this.topologyVersion = this.error?.topologyVersion ?? hello?.topologyVersion ?? null;
- this.setName = hello?.setName ?? null;
- this.setVersion = hello?.setVersion ?? null;
- this.electionId = hello?.electionId ?? null;
- this.logicalSessionTimeoutMinutes = hello?.logicalSessionTimeoutMinutes ?? null;
- this.primary = hello?.primary ?? null;
- this.me = hello?.me?.toLowerCase() ?? null;
- this.$clusterTime = hello?.$clusterTime ?? null;
- }
- get hostAddress() {
- return utils_1.HostAddress.fromString(this.address);
- }
- get allHosts() {
- return this.hosts.concat(this.arbiters).concat(this.passives);
- }
- /** Is this server available for reads*/
- get isReadable() {
- return this.type === common_1.ServerType.RSSecondary || this.isWritable;
- }
- /** Is this server data bearing */
- get isDataBearing() {
- return DATA_BEARING_SERVER_TYPES.has(this.type);
- }
- /** Is this server available for writes */
- get isWritable() {
- return WRITABLE_SERVER_TYPES.has(this.type);
- }
- get host() {
- const chopLength = `:${this.port}`.length;
- return this.address.slice(0, -chopLength);
- }
- get port() {
- const port = this.address.split(':').pop();
- return port ? Number.parseInt(port, 10) : 27017;
- }
- /**
- * Determines if another `ServerDescription` is equal to this one per the rules defined
- * in the {@link https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#serverdescription|SDAM spec}
- */
- equals(other) {
- // Despite using the comparator that would determine a nullish topologyVersion as greater than
- // for equality we should only always perform direct equality comparison
- const topologyVersionsEqual = this.topologyVersion === other?.topologyVersion ||
- compareTopologyVersion(this.topologyVersion, other?.topologyVersion) === 0;
- const electionIdsEqual = this.electionId != null && other?.electionId != null
- ? (0, utils_1.compareObjectId)(this.electionId, other.electionId) === 0
- : this.electionId === other?.electionId;
- return (other != null &&
- (0, utils_1.errorStrictEqual)(this.error, other.error) &&
- this.type === other.type &&
- this.minWireVersion === other.minWireVersion &&
- (0, utils_1.arrayStrictEqual)(this.hosts, other.hosts) &&
- tagsStrictEqual(this.tags, other.tags) &&
- this.setName === other.setName &&
- this.setVersion === other.setVersion &&
- electionIdsEqual &&
- this.primary === other.primary &&
- this.logicalSessionTimeoutMinutes === other.logicalSessionTimeoutMinutes &&
- topologyVersionsEqual);
- }
- }
- exports.ServerDescription = ServerDescription;
- // Parses a `hello` message and determines the server type
- function parseServerType(hello, options) {
- if (options?.loadBalanced) {
- return common_1.ServerType.LoadBalancer;
- }
- if (!hello || !hello.ok) {
- return common_1.ServerType.Unknown;
- }
- if (hello.isreplicaset) {
- return common_1.ServerType.RSGhost;
- }
- if (hello.msg && hello.msg === 'isdbgrid') {
- return common_1.ServerType.Mongos;
- }
- if (hello.setName) {
- if (hello.hidden) {
- return common_1.ServerType.RSOther;
- }
- else if (hello.isWritablePrimary) {
- return common_1.ServerType.RSPrimary;
- }
- else if (hello.secondary) {
- return common_1.ServerType.RSSecondary;
- }
- else if (hello.arbiterOnly) {
- return common_1.ServerType.RSArbiter;
- }
- else {
- return common_1.ServerType.RSOther;
- }
- }
- return common_1.ServerType.Standalone;
- }
- exports.parseServerType = parseServerType;
- function tagsStrictEqual(tags, tags2) {
- const tagsKeys = Object.keys(tags);
- const tags2Keys = Object.keys(tags2);
- return (tagsKeys.length === tags2Keys.length &&
- tagsKeys.every((key) => tags2[key] === tags[key]));
- }
- /**
- * Compares two topology versions.
- *
- * 1. If the response topologyVersion is unset or the ServerDescription's
- * topologyVersion is null, the client MUST assume the response is more recent.
- * 1. If the response's topologyVersion.processId is not equal to the
- * ServerDescription's, the client MUST assume the response is more recent.
- * 1. If the response's topologyVersion.processId is equal to the
- * ServerDescription's, the client MUST use the counter field to determine
- * which topologyVersion is more recent.
- *
- * ```ts
- * currentTv < newTv === -1
- * currentTv === newTv === 0
- * currentTv > newTv === 1
- * ```
- */
- function compareTopologyVersion(currentTv, newTv) {
- if (currentTv == null || newTv == null) {
- return -1;
- }
- if (!currentTv.processId.equals(newTv.processId)) {
- return -1;
- }
- // TODO(NODE-2674): Preserve int64 sent from MongoDB
- const currentCounter = bson_1.Long.isLong(currentTv.counter)
- ? currentTv.counter
- : bson_1.Long.fromNumber(currentTv.counter);
- const newCounter = bson_1.Long.isLong(newTv.counter) ? newTv.counter : bson_1.Long.fromNumber(newTv.counter);
- return currentCounter.compare(newCounter);
- }
- exports.compareTopologyVersion = compareTopologyVersion;
- //# sourceMappingURL=server_description.js.map
|