"use strict";
const events = require("events");
const { throwNotSupported } = require("./new-utils");
const _rust = require("../index");
/**
* Represents a Cassandra node.
* @extends EventEmitter
*/
class Host extends events.EventEmitter {
/**
* Creates a new Host instance.
*/
constructor() {
super();
/**
* Gets ip address and port number of the node separated by `:`.
* @type {String}
*/
this.address = null;
/**
* Gets string containing the Cassandra version.
* @type {String}
*/
this.cassandraVersion = null;
/**
* Gets data center name of the node.
* @type {String}
*/
this.datacenter = null;
/**
* Gets rack name of the node.
* @type {String}
*/
this.rack = null;
/**
* Gets the tokens assigned to the node.
* @type {Array}
*/
this.tokens = null;
/**
* Gets the id of the host.
*
* This identifier is used by the server for internal communication / gossip.
* @type {Uuid}
*/
this.hostId = null;
}
/**
* @deprecated Not supported by the driver. Usage will throw an error.
*/
get dseVersion() {
throwNotSupported("Host.dseVersion");
return null;
}
set dseVersion(_) {
throwNotSupported("Host.dseVersion");
}
/**
* @deprecated Not supported by the driver. Usage will throw an error.
*/
get workloads() {
throwNotSupported("Host.workloads");
return null;
}
set workloads(_) {
throwNotSupported("Host.workloads");
}
/**
* This endpoint is not yet implemented, and its usage will throw an error
*
* Determines if the node is UP now (seen as UP by the driver).
* @returns {boolean}
*/
isUp() {
throw new Error(`TODO: Not implemented`);
}
/**
* This endpoint is not yet implemented, and its usage will throw an error
*
* Determines if the host can be considered as UP.
* Deprecated: Use {@link Host#isUp()} instead.
* @returns {boolean}
*/
canBeConsideredAsUp() {
throw new Error(`TODO: Not implemented`);
}
/**
* This endpoint is not yet implemented, and its usage will throw an error
*
* Returns an array containing the Cassandra Version as an Array of Numbers having the major version in the first
* position.
* @returns {Array.<Number>}
*/
getCassandraVersion() {
// We never set the version when creating object from Rust,
// so we will explicitly throw an error, when someone attempts to get the version
// to avoid any confusion
throw new Error(`TODO: Not implemented`);
// if (!this.cassandraVersion) {
// return utils.emptyArray;
// }
// return this.cassandraVersion
// .split("-")[0]
// .split(".")
// .map((x) => parseInt(x, 10));
}
/**
* @deprecated Not supported by the driver. Usage will throw an error.
*/
getDseVersion() {
throwNotSupported("Host.getDseVersion");
}
/**
* Creates a Host instance from a Rust HostWrapper.
* @param {_rust.HostWrapper} hostWrapper
* @package
*/
static fromRust(hostWrapper) {
let host = new Host();
host.address = hostWrapper.address;
host.datacenter = hostWrapper.datacenter;
host.rack = hostWrapper.rack;
host.hostId = hostWrapper.hostId;
return host;
}
}
/**
* Represents an associative-array of {@link Host hosts} that can be iterated.
* It creates an internal copy when adding or removing, making it safe to iterate using the values()
* method within async operations.
* @extends events.EventEmitter
* @constructor
*/
class HostMap extends events.EventEmitter {
constructor() {
super();
this._items = new Map();
this._values = null;
Object.defineProperty(this, "length", {
get: () => this.values().length,
enumerable: true,
});
/**
* Emitted when a host is added to the map
* @event HostMap#add
*/
/**
* Emitted when a host is removed from the map
* @event HostMap#remove
*/
}
/**
* Executes a provided function once per map element.
* @param callback
*/
forEach(callback) {
const items = this._items;
for (const [key, value] of items) {
callback(value, key);
}
}
/**
* Gets a {@link Host host} by key or undefined if not found.
* @param {String} key
* @returns {Host}
*/
get(key) {
return this._items.get(key);
}
/**
* Returns an array of host addresses.
* @returns {Array.<String>}
*/
keys() {
return Array.from(this._items.keys());
}
/**
* # WARNING:
* Editing host map does not affect the connection to the database.
* You only edit the local copy of the connected hosts.
*
* Removes an item from the map.
* @param {String} key The key of the host
* @fires HostMap#remove
* @deprecated Editing underlying connections will not be supported in this driver
*/
remove(key) {
const value = this._items.get(key);
if (value === undefined) {
return;
}
// Clear cache
this._values = null;
// Copy the values
const copy = new Map(this._items);
copy.delete(key);
this._items = copy;
this.emit("remove", value);
}
/**
* # WARNING:
* Editing host map does not affect the connection to the database.
* You only edit the local copy of the connected hosts.
*
* Removes multiple hosts from the map.
* @param {Array.<String>} keys
* @fires HostMap#remove
* @deprecated Editing underlying connections will not be supported in this driver
*/
removeMultiple(keys) {
// Clear value cache
this._values = null;
// Copy the values
const copy = new Map(this._items);
const removedHosts = [];
for (const key of keys) {
const h = copy.get(key);
if (!h) {
continue;
}
removedHosts.push(h);
copy.delete(key);
}
this._items = copy;
removedHosts.forEach((h) => this.emit("remove", h));
}
/**
* # WARNING:
* Editing host map does not affect the connection to the database.
* You only edit the local copy of the connected hosts.
*
* Adds a new item to the map.
* @param {String} key The key of the host
* @param {Host} value The host to be added
* @fires HostMap#remove
* @fires HostMap#add
* @deprecated Editing underlying connections will not be supported in this driver
*/
set(key, value) {
// Clear values cache
this._values = null;
const originalValue = this._items.get(key);
if (originalValue) {
// The internal structure does not change
this._items.set(key, value);
// emit a remove followed by a add
this.emit("remove", originalValue);
this.emit("add", value);
return;
}
// Copy the values
const copy = new Map(this._items);
copy.set(key, value);
this._items = copy;
this.emit("add", value);
return value;
}
/**
* Returns a shallow copy of the values of the map.
* @returns {Array.<Host>}
*/
values() {
if (!this._values) {
// Cache the values
this._values = Object.freeze(Array.from(this._items.values()));
}
return this._values;
}
/**
* # WARNING:
* Editing host map does not affect the connection to the database.
* You only edit the local copy of the connected hosts.
*
* Removes all items from the map.
* @returns {Array.<Host>} The previous items
* @deprecated Editing underlying connections will not be supported in this driver
*/
clear() {
const previousItems = this.values();
// Clear cache
this._values = null;
// Clear items
this._items = new Map();
// Emit events
previousItems.forEach((h) => this.emit("remove", h));
return previousItems;
}
inspect() {
return this._items;
}
toJSON() {
// Node.js 10 and below don't support Object.fromEntries()
if (Object.fromEntries) {
return Object.fromEntries(this._items);
}
const obj = {};
for (const [key, value] of this._items) {
obj[key] = value;
}
return obj;
}
/**
* Converts a list of HostWrapper from Rust to a HostMap
* @param {Array.<_rust.HostWrapper>} hostsList
* @package
*/
static fromRust(hostsList) {
const hostMap = new HostMap();
for (const hostWrapper of hostsList) {
hostMap._items.set(hostWrapper.address, Host.fromRust(hostWrapper));
}
return hostMap;
}
}
module.exports = {
Host,
HostMap,
};