Source: sharding/ShardStatus.js

// 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;