// Copyright 2020 Campbell Crowley. All rights reserved.
// Author: Campbell Crowley (web@campbellcrowley.com)
/**
* @description Stores information about a single shard that is sent to the
* master.
* @class
* @memberof ShardingMaster
* @inner
* @static
*/
class ShardStatus {
/**
* @description Create new instance.
* @param {string} id The ID of the shard this status object contains data
* for.
*/
constructor(id) {
if (typeof id !== 'string' || id.length < 3) {
throw new TypeError('Invalid Shard ID for ShardStatus object: ' + id);
}
/**
* @description The ID of the shard this status object contains data for.
* @public
* @type {string}
*/
this.id = id;
/**
* @description Is this shard considered the master shard. There must be
* exactly one of these configured at all times, and in most cases can run
* in the same directory as the ShardingMaster. This shard will be told to
* not connect to Discord, and act as the master node for web requests.
* @public
* @type {boolean}
* @default
*/
this.isMaster = false;
/**
* @description The timestamp at which the shard was most recently started.
* @public
* @type {number}
* @default
*/
this.startTime = 0;
/**
* @description The timestamp at which the shard was most recently stopped.
* @public
* @type {number}
* @default
*/
this.stopTime = 0;
/**
* @description The goal Discord shard ID of this shard. Similar to
* {@link ShardingMaster.ShardInfo~goalShardId}, and is used to ensure
* messages were received properly.
* @public
* @type {number}
* @default
*/
this.goalShardId = -1;
/**
* @description The current Discord shard ID of this shard. Similar to
* {@link ShardingMaster.ShardInfo~currentShardId}, and will in most cases
* update that value once received by the master.
* @public
* @type {number}
* @default
*/
this.currentShardId = -1;
/**
* @description The goal Discord shard count this is configured for.
* @public
* @type {number}
* @default
*/
this.goalShardCount = -1;
/**
* @description The current Discord shard count this is configured for.
* @public
* @type {number}
* @default
*/
this.currentShardCount = -1;
/**
* @description The timestamp at which this status was generated. This
* defaults to `Date.now()`, but is expected to be overridden to a more
* accurate value.
* @public
* @type {number}
* @default
*/
this.timestamp = Date.now();
/**
* @description The difference in time since the previous status update in
* milliseconds. A value of 0 can be assumed to mean this is the first
* update in a series.
* @public
* @type {number}
* @default
*/
this.timeDelta = 0;
/**
* @description The number of Discord messages received during the time
* since the previous status update.
* @public
* @type {number}
* @default
*/
this.messageCountDelta = 0;
/**
* @description The number of Discord messages received during the entire
* time the shard has been running (resets if shard reboots).
* @public
* @type {number}
* @default
*/
this.messageCountTotal = 0;
/**
* @description The amount of memory in use of the shard's heap in bytes.
* @public
* @type {number}
* @default
*/
this.memHeapUsed = 0;
/**
* @description The total memory currently available to the shard's heap in
* bytes. This value will expand as the total is reached, until the
* configured max has been reached, at which it will crash due to failing to
* allocate more memory.
* @public
* @type {number}
* @default
*/
this.memHeapTotal = 0;
/**
* @description Resident Set Size. Total allocated memory for the entire
* process.
* @public
* @type {number}
* @default
*/
this.memRSS = 0;
/**
* @description Memory usage of C++ objects bound to JavaScript objects
* managed by V8.
* @public
* @type {number}
* @default
*/
this.memExternal = 0;
/**
* @description The percentage of time each CPU core has been used since the
* last status update.
* @public
* @type {number[]}
* @default
*/
this.cpuLoad = [0];
/**
* @description Raw values from the OS about CPU times. Each element in the
* array is a single processor thread (hyperthreading can increase the count
* above the number of cores). From `os.cpus()`. Used to calculate
* {@link cpuLoad}.
* @public
* @type {Array.<{
* model: string,
* speed: number,
* times: {
* user: number,
* nice: number,
* sys: number,
* idle: number,
* irq: number
* }
* }>}
*/
this.cpus = [];
/**
* @description The average ping time from the shard to Discord since the
* last status update.
* @public
* @type {number}
* @default
*/
this.ping = 0;
/**
* @description The total storage space used by the bot in its installed
* directory in bytes.
* @public
* @type {number}
* @default
*/
this.storageUsedTotal = 0;
/**
* @description The total storage space used by user data.
* @public
* @type {number}
* @default
*/
this.storageUsedUsers = 0;
}
/**
* @description Reset all necessary values to clear the state of the previous
* instance.
* @public
*/
reset() {
this.timestamp = Date.now();
this.timeDelta = 0;
this.messageCountDelta = 0;
this.messageCountTotal = 0;
this.memHeapUsed = 0;
this.memHeapTotal = 0;
this.memRSS = 0;
this.memExternal = 0;
this.cpuLoad = [0];
this.cpus = [];
this.ping = 0;
this.storageUsedTotal = 0;
this.storageUsedUsers = 0;
}
/**
* @description Convert a given object to a ShardStatus object. Values are
* only copied if their types exactly match.
* @public
* @static
* @param {object} obj The ShardStatus-like object to copy.
* @param {string} [id] If the given object does not specify the shard's ID,
* it may be passed here instead.
* @returns {ShardingMaster.ShardStatus} Created ShardStatus object.
*/
static from(obj, id) {
const out = new ShardStatus(id || obj.id);
for (const prop of Object.keys(out)) {
if (prop === 'id') continue;
if (typeof out[prop] === 'function') continue;
if (typeof out[prop] !== typeof obj[prop]) continue;
out[prop] = obj[prop];
}
return out;
}
/**
* @description Update the current object with values received.
* @public
* @param {object} obj The object with values to copy over.
*/
update(obj) {
for (const prop of Object.keys(this)) {
if (prop === 'id') continue;
if (typeof this[prop] === 'function') continue;
if (typeof this[prop] !== typeof obj[prop]) continue;
this[prop] = obj[prop];
}
}
}
module.exports = ShardStatus;