### Initialize ClusterManager with ReClusterManager Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md This example shows how to set up a ClusterManager and extend it with the ReClusterManager for zero downtime reclustering. It includes starting the reclustering process with a specified restart mode. ```javascript // Typescript: import { ClusterManager, ReClusterManager } from 'discord-hybrid-sharding' const { ClusterManager, ReClusterManager } = require('discord-hybrid-sharding'); const manager = new ClusterManager(`${__dirname}/bot.js`, {...}); manager.extend( new ReClusterManager() ) ... ///SOME CODE // Start reclustering const optional = {totalShards, totalClusters....} manager.recluster?.start({restartMode: 'gracefulSwitch', ...optional}) ``` -------------------------------- ### Install discord-hybrid-sharding Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Install the discord-hybrid-sharding package using npm. This is the first step to integrating hybrid sharding into your Discord bot. ```cli npm i discord-hybrid-sharding ``` -------------------------------- ### Cluster Manager IPC Setup Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Sets up the ClusterManager to listen for messages from clients. Handles custom requests and sends replies. Spawns clusters and sends periodic 'alive' messages. ```javascript // Typescript: import { ClusterManager, messageType } from 'discord-hybrid-sharding' const { ClusterManager, messageType } = require('discord-hybrid-sharding'); const manager = new ClusterManager(`${__dirname}/testbot.js`, { totalShards: 1, totalClusters: 1, }); manager.on('clusterCreate', cluster => { cluster.on('message', message => { console.log(message); if (message._type !== messageType.CUSTOM_REQUEST) return; // Check if the message needs a reply message.reply({ content: 'hello world' }); }); setInterval(() => { cluster.send({ content: 'I am alive' }); // Send a message to the client cluster.request({ content: 'Are you alive?', alive: true }).then(e => console.log(e)); // Send a message to the client }, 5000); }); manager.spawn({ timeout: -1 }); ``` -------------------------------- ### Initialize ClusterManager with HeartbeatManager Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md This example shows how to extend the ClusterManager with the HeartbeatManager to monitor cluster responsiveness. It configures the interval for sending heartbeats and the maximum number of missed heartbeats before a cluster is respawned. ```javascript // Typescript: import { ClusterManager, HeartbeatManager } from 'discord-hybrid-sharding' const { ClusterManager, HeartbeatManager } = require('discord-hybrid-sharding'); const manager = new ClusterManager(`${__dirname}/bot.js`, {...}); manager.extend( new HeartbeatManager({ interval: 2000, // Interval to send a heartbeat maxMissedHeartbeats: 5, // Maximum amount of missed Heartbeats until Cluster will get respawned }) ) ``` -------------------------------- ### Get Shard List in Current Cluster Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Provides examples for retrieving the list of shard IDs and the collection of WebSocket shards within the current cluster. ```diff - client.shard.id + client.cluster.shardList // Array of internal shard ids + client.cluster.shards // Collection of ws shards ``` -------------------------------- ### Cluster Client IPC Setup Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Initializes the ClusterClient within a Discord client instance. Listens for messages from the cluster manager, handles custom requests, and sends periodic 'alive' messages. ```javascript // Typescript: import { ClusterClient, getInfo, messageType } from 'discord-hybrid-sharding' const { ClusterClient, getInfo, messageType } = require('discord-hybrid-sharding'); const Discord = require('discord.js'); const client = new Discord.Client({ shards: getInfo().SHARD_LIST, // An array of shards that will get spawned shardCount: getInfo().data.TOTAL_SHARDS, // Total number of shards }); client.cluster = new ClusterClient(client); client.cluster.on('message', message => { console.log(message); if (message._type !== messageType.CUSTOM_REQUEST) return; // Check if the message needs a reply if (message.alive) message.reply({ content: 'Yes I am!' }); }); setInterval(() => { client.cluster.send({ content: 'I am alive as well!' }); }, 5000); client.login('YOUR_TOKEN'); ``` -------------------------------- ### Get Total Shards Count Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Demonstrates how to access the total number of shards, now available through 'client.cluster.info.TOTAL_SHARDS' instead of 'client.shard.count'. ```diff - client.shard.count + client.cluster.info.TOTAL_SHARDS ``` -------------------------------- ### Evaluate Guild Count Over Clusters Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Use broadcastEval to execute code across all clusters and aggregate results. This example calculates the total number of guilds across all shards. ```javascript client.cluster .broadcastEval(`this.guilds.cache.size`) .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)); ``` ```javascript // or with a callback function client.cluster .broadcastEval(c => c.guilds.cache.size) .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`)); ``` -------------------------------- ### Get Current Cluster ID Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Illustrates how to retrieve the current cluster's ID, changing from 'client.shard.id' to 'client.cluster.id'. ```diff - client.shard.id + client.cluster.id ``` -------------------------------- ### Manual Cluster Spawning with Queue Control Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Control the order and pacing of cluster spawns by disabling auto-queue mode. Manually advance the queue using `manager.queue.next()` when ready, for example, after database warm-up. Use `queue.stop()` and `queue.resume()` to pause and resume spawning. ```typescript // cluster.js — manual queue mode const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 8, shardsPerClusters: 2, token: process.env.DISCORD_TOKEN, queue: { auto: false }, }); manager.on('clusterReady', async cluster => { console.log(`Cluster ${cluster.id} ready — triggering next spawn`); // Advance to the next item in the queue when you're ready await manager.queue.next(); }); // Start filling the queue but DON'T auto-drain it manager.spawn(); // Kick off the first cluster manually await manager.queue.next(); // At any point you can pause and resume: manager.queue.stop(); // block further .next() calls manager.queue.resume(); // unblock ``` ```typescript // bot.js — trigger next cluster from inside a cluster process client.cluster.spawnNextCluster(); ``` -------------------------------- ### Get Current Shard ID Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Shows the updated method for obtaining the current shard ID, which is now accessed via 'message.guild.shardId' instead of 'client.shard.id'. ```diff - client.shard.id + message.guild.shardId ``` -------------------------------- ### Initialize ClusterClient in Bot.js Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md This snippet demonstrates how to initialize a ClusterClient within the bot's main file, handle maintenance mode, and trigger the 'ready' event after loading necessary data. ```javascript // Typescript: import { ClusterClient, getInfo } from 'discord-hybrid-sharding' const { ClusterClient, getInfo } = require('discord-hybrid-sharding'); const client = new Discord.Client(...) client.cluster = new ClusterClient(client); if (client.cluster.maintenance) console.log(`Bot on maintenance mode with ${client.cluster.maintenance}`); client.cluster.on('ready', () => { // Load Events // Handle Database stuff, to not process outdated data }); // Can also be in a separate event handler. The triggerReady must be called. client.on("clientReady", (readyClient) => { readyClient.cluster.triggerReady(); }) client.login(token); ``` -------------------------------- ### Add Cluster Ready Trigger Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md This snippet shows how to manually trigger the 'clientReady' event for cluster readiness, which is not handled by the library to maintain library-agnosticism. ```diff + client.on("clientReady", (readyClient) => { + readyClient.cluster.triggerReady(); + }) ``` -------------------------------- ### Initialize ClusterManager Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Create a ClusterManager instance to manage bot processes. Configure total shards, shards per cluster, mode, and your bot token. The manager spawns clusters and logs when they are launched. ```javascript const { ClusterManager } = require('discord-hybrid-sharding'); const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 'auto', // or numeric shard count /// Check below for more options shardsPerClusters: 2, // 2 shards per process // totalClusters: 7, mode: 'process', // you can also choose "worker" token: 'YOUR_TOKEN', }); manager.on('clusterCreate', cluster => console.log(`Launched Cluster ${cluster.id}`)); manager.spawn({ timeout: -1 }); ``` -------------------------------- ### ClusterManager Initialization and Spawning Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Demonstrates how to initialize and use the ClusterManager to spawn and manage clusters for your Discord bot. This is the central orchestrator for distributing shards across processes. ```APIDOC ## ClusterManager — Initialize and spawn clusters `ClusterManager` is the central orchestrator. It reads shard/cluster count options, slices the shard list into chunks, and spawns each chunk as an isolated process or worker thread. It extends `EventEmitter` and exposes methods for broadcasting evals, respawning, and registering plugins. ### Usage Example: ```ts // cluster.js (entry point — run with: node cluster.js) import { ClusterManager } from 'discord-hybrid-sharding'; const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 'auto', // ask Discord for recommended count shardsPerClusters: 4, // 4 internal shards per process mode: 'process', // 'process' | 'worker' token: process.env.DISCORD_TOKEN, respawn: true, restarts: { max: 5, // max auto-restarts per interval interval: 3_600_000, // reset counter every hour }, spawnOptions: { delay: 7000, // ms between cluster spawns (≥7 s to avoid rate-limits) timeout: -1, // -1 = no ready timeout }, }); manager.on('clusterCreate', cluster => console.log(`Cluster ${cluster.id} created (shards: ${cluster.shardList}) `); manager.on('clusterReady', cluster => console.log(`Cluster ${cluster.id} is ready `); manager.on('debug', msg => console.debug('[DEBUG]', msg)); // Spawns all clusters and waits for the queue to drain await manager.spawn({ timeout: -1 }); ``` ``` -------------------------------- ### Initialize and Spawn Clusters with ClusterManager Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Use ClusterManager in your entry point file to configure and spawn child processes or worker threads for your Discord bot. Set shard counts, modes, and spawn delays to optimize resource usage and avoid rate limits. ```typescript import { ClusterManager } from 'discord-hybrid-sharding'; const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 'auto', shardsPerClusters: 4, mode: 'process', token: process.env.DISCORD_TOKEN, respawn: true, restarts: { max: 5, interval: 3_600_000, }, spawnOptions: { delay: 7000, timeout: -1, }, }); manager.on('clusterCreate', cluster => console.log(`Cluster ${cluster.id} created (shards: ${cluster.shardList})`), ); manager.on('clusterReady', cluster => console.log(`Cluster ${cluster.id} is ready`), ); manager.on('debug', msg => console.debug('[DEBUG]', msg)); await manager.spawn({ timeout: -1 }); ``` -------------------------------- ### Integrate discord-hybrid-sharding with Other Libraries Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Use this code in your bot's main file when integrating with other libraries. It requires importing ClusterClient and getInfo, and initializing ClusterClient with your Discord client instance. ```javascript // Typescript: import { ClusterClient, getInfo } from 'discord-hybrid-sharding' const { ClusterClient, getInfo } = require('discord-hybrid-sharding'); ///Create your Discord Client: /* Use the Data below for telling the Client, which shards to spawn */ const lastShard = getInfo().LAST_SHARD_ID; const firstShard = getInfo().FIRST_SHARD_ID; const totalShards = getInfo().TOTAL_SHARDS; const shardList = getInfo().SHARD_LIST; client.cluster = new ClusterClient(client); ///When the Client is ready, You can listen to the client's ready event: // Just add, when the client.on('ready') does not exist client.cluster.triggerReady(); ``` -------------------------------- ### getInfo Function Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Explains how to use the `getInfo()` function to retrieve cluster environment data, such as shard lists, total shard counts, and cluster IDs, from within a cluster process. ```APIDOC ## getInfo — Read cluster environment data `getInfo()` parses `process.env` (process mode) or `workerData` (worker mode) and returns a typed `ClusterClientData` object. Call it anywhere inside a cluster process to access shard/cluster configuration without passing arguments manually. ### Usage Example: ```ts import { getInfo } from 'discord-hybrid-sharding'; const info = getInfo(); // Example output: // { // SHARD_LIST: [0, 1, 2, 3], // TOTAL_SHARDS: 16, // CLUSTER: 0, // CLUSTER_COUNT: 4, // CLUSTER_MANAGER_MODE: 'process', // FIRST_SHARD_ID: 0, // LAST_SHARD_ID: 3, // MAINTENANCE: undefined, // CLUSTER_QUEUE_MODE: 'auto', // } console.log(`This process owns shards ${info.FIRST_SHARD_ID}–${info.LAST_SHARD_ID}`); console.log(`Total shards across all clusters: ${info.TOTAL_SHARDS}`); ``` ``` -------------------------------- ### Refactor bot.js for Sharding Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Adapt your main bot file to accept sharding parameters from ClusterClient. Initialize Discord.js client with shard information and set up ClusterClient for inter-cluster communication. ```javascript const { ClusterClient, getInfo } = require('discord-hybrid-sharding'); const Discord = require('discord.js'); const client = new Discord.Client({ shards: getInfo().SHARD_LIST, // An array of shards that will get spawned shardCount: getInfo().TOTAL_SHARDS, // Total number of shards intents: [], }); client.cluster = new ClusterClient(client); // initialize the Client, so we access the .broadcastEval() // Can also be in a separate event handler. The triggerReady must be called. client.on("clientReady", (readyClient) => { readyClient.cluster.triggerReady(); }) client.login('YOUR_TOKEN'); ``` -------------------------------- ### Initialize AutoResharderManager Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Use this to enable automatic re-sharding. Configure guild limits per shard and cluster settings. Ensure 'discord-hybrid-sharding' is imported. ```javascript const { ClusterManager, AutoResharderManager } = require('discord-hybrid-sharding'); const manager = new ClusterManager(`${__dirname}/bot.js`, {...}); manager.extend( new AutoResharderManager(this.cluster, { debug: true, ShardsPerCluster: 'useManagerOption', MinGuildsPerShard: 1400, MaxGuildsPerShard: 2400, }); ) ``` -------------------------------- ### Update respawnAll Options Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Shows the renaming of options in the respawnAll method from 'shardDelay' to 'clusterDelay' and 'respawnDelay' for both client and manager. ```diff - client.shard.respawnAll({ shardDelay = 5000, respawnDelay = 500, timeout = 30000 }) + client.cluster.respawnAll({ clusterDelay: 5000, respawnDelay: 5500, timeout: 30000 }) ``` ```diff - manager.shard.respawnAll({ shardDelay = 5000, respawnDelay = 500, timeout = 30000 }) + manager.respawnAll({ clusterDelay: 5000, respawnDelay: 5500, timeout: 30000 }) ``` -------------------------------- ### Configure Restart Limits Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Set maximum restarts per cluster and the interval for resetting the restart count. This helps prevent excessive restarts. ```javascript const manager = new ClusterManager(`${__dirname}/bot.js`, { ...YourOptions, restarts: { max: 5, interval: 60000 * 60, }, }); ``` -------------------------------- ### Queue Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Controls the order and pacing of cluster spawns. Allows manual advancement of the spawn queue. ```APIDOC ## Queue — Fine-grained cluster spawn control The `Queue` controls the order and pacing of cluster spawns. By setting `queue.auto` to `false` you can manually advance the queue, e.g. only spawning the next cluster once your database is warmed up. ### Manual Queue Mode: ```ts // cluster.js — manual queue mode const manager = new ClusterManager('./bot.js', { totalShards: 8, shardsPerClusters: 2, token: process.env.DISCORD_TOKEN, queue: { auto: false }, }); manager.on('clusterReady', async cluster => { console.log(`Cluster ${cluster.id} ready — triggering next spawn`); // Advance to the next item in the queue when you're ready await manager.queue.next(); }); // Start filling the queue but DON'T auto-drain it manager.spawn(); // Kick off the first cluster manually await manager.queue.next(); // Pause and resume the queue: manager.queue.stop(); // block further .next() calls manager.queue.resume(); // unblock ``` ### Triggering Next Cluster from within a Cluster: ```ts // bot.js — trigger next cluster from inside a cluster process client.cluster.spawnNextCluster(); ``` ``` -------------------------------- ### Update AutoResharder Options Dynamically Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Demonstrates how to dynamically change AutoResharder options while the bot is running using `evalOnManager`. ```typescript cluster.evalOnManager(manager => { manager.autoresharder.options.MinGuildsPerShard = 1; manager.autoresharder.options.MaxGuildsPerShard = 10; return true; }) ``` -------------------------------- ### Attach ClusterClient Bridge in Bot Process Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt In each spawned cluster process, use ClusterClient to wrap your Discord client. This provides cluster metadata and enables cross-cluster communication. Call triggerReady() after your client is ready to signal the manager. ```typescript import { ClusterClient, getInfo } from 'discord-hybrid-sharding'; import { Client, GatewayIntentBits } from 'discord.js'; const info = getInfo(); const client = new Client({ shards: info.SHARD_LIST, shardCount: info.TOTAL_SHARDS, intents: [GatewayIntentBits.Guilds], }); client.cluster = new ClusterClient(client); console.log('Cluster ID :', client.cluster.id); console.log('Cluster count:', client.cluster.count); console.log('Shard list :', client.cluster.shardList); client.once('ready', readyClient => { console.log(`Logged in as ${readyClient.user.tag}`); readyClient.cluster.triggerReady(); }); client.login(process.env.DISCORD_TOKEN); ``` -------------------------------- ### ClusterClient Integration Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Details on how to integrate `ClusterClient` within your bot's main file to manage the Discord client and enable cross-cluster communication. It wraps the Discord client and exposes cluster metadata. ```APIDOC ## ClusterClient — Attach the client-side bridge `ClusterClient` runs inside each spawned process/worker. It wraps the Discord client, exposes cluster metadata through `getInfo()`, and provides all cross-cluster communication methods. Call `triggerReady()` from your client's ready event so the manager can mark the cluster as online. ### Usage Example: ```ts // bot.js (executed once per cluster) import { ClusterClient, getInfo } from 'discord-hybrid-sharding'; import { Client, GatewayIntentBits } from 'discord.js'; const info = getInfo(); const client = new Client({ shards: info.SHARD_LIST, // exact shard IDs this process handles shardCount: info.TOTAL_SHARDS, // global shard total intents: [GatewayIntentBits.Guilds], }); client.cluster = new ClusterClient(client); // Expose cluster metadata console.log('Cluster ID :', client.cluster.id); console.log('Cluster count:', client.cluster.count); console.log('Shard list :', client.cluster.shardList); client.once('ready', readyClient => { console.log(`Logged in as ${readyClient.user.tag}`); readyClient.cluster.triggerReady(); // signal manager: cluster is up }); client.login(process.env.DISCORD_TOKEN); ``` ``` -------------------------------- ### Rolling restart of all clusters with ClusterManager#respawnAll Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Performs a rolling restart by killing and re-spawning clusters sequentially, with configurable delays between each operation. ```typescript // cluster.js await manager.respawnAll({ clusterDelay: 5500, // ms to wait between restarting each cluster respawnDelay: 5500, // ms the cluster itself waits before spawning timeout: -1, // ready timeout per cluster (-1 = no limit) }); console.log('All clusters have been respawned'); ``` -------------------------------- ### Update BroadcastEval Options Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Demonstrates the change in broadcastEval options from 'shard' to 'cluster' for specifying the target cluster. ```diff - .broadcastEval((c, context) => c.guilds.cache.get(context.guildId), { context: { guildId: '1234' }, shard: 0 }) + .broadcastEval((c, context) => c.guilds.cache.get(context.guildId), { context: { guildId: '1234' }, cluster: 0 }) ``` -------------------------------- ### ClusterManager#respawnAll Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Rolling restart of all clusters. This method kills and re-spawns every cluster sequentially, honouring configurable delays between each respawn. ```APIDOC ## ClusterManager#respawnAll — Rolling restart of all clusters Kills and re-spawns every cluster sequentially, honouring configurable delays between each respawn. ### Parameters - `options` (object, optional): Options for respawning. - `clusterDelay` (number, optional): Milliseconds to wait between restarting each cluster. - `respawnDelay` (number, optional): Milliseconds the cluster itself waits before spawning. - `timeout` (number, optional): Ready timeout per cluster (-1 = no limit). ### Request Example ```ts // cluster.js await manager.respawnAll({ clusterDelay: 5500, // ms to wait between restarting each cluster respawnDelay: 5500, // ms the cluster itself waits before spawning timeout: -1, // ready timeout per cluster (-1 = no limit) }); console.log('All clusters have been respawned'); ``` ``` -------------------------------- ### Manual Queue Progression Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Manually spawns the next cluster in the queue using `manager.queue.next()`. This function is typically called after disabling the automatic queue. ```javascript manager.spawn(); manager.queue.next(); ``` -------------------------------- ### ClusterManager#broadcastEval Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Run code on every cluster. This method serializes a function or string and executes it within the context of the Discord client on each cluster, or a specific cluster, shard, or guild. Results are collected into an array. ```APIDOC ## ClusterManager#broadcastEval — Run code on every cluster `broadcastEval` serialises a function (or string) and executes it in the context of the Discord client on each cluster (or a specific cluster/shard/guild). Results are collected into an array. ### Parameters - `func` (Function | string): The function or string to evaluate. - `options` (object, optional): Options for the evaluation. - `context` (object, optional): Context to pass to the function. - `cluster` (number, optional): The specific cluster to target. - `guildId` (string, optional): The guild ID to target (auto-resolves to the correct shard/cluster). - `timeout` (number, optional): Timeout in milliseconds for the evaluation. ### Request Example ```ts // 1. Get guild count from every cluster const guildCounts: number[] = await manager.broadcastEval( (client) => client.guilds.cache.size, ); const total = guildCounts.reduce((a, b) => a + b, 0); console.log(`Total guilds: ${total}`); // 2. Pass context to the function const guildName: string[] = await manager.broadcastEval( (client, ctx) => client.guilds.cache.get(ctx.guildId)?.name ?? null, { context: { guildId: '123456789012345678' } }, ); console.log('Guild name:', guildName.filter(Boolean)[0]); // 3. Target a single cluster const result = await manager.broadcastEval( (client) => client.uptime, { cluster: 2 }, ); console.log('Cluster 2 uptime:', result[0]); // 4. Target by guild ID (auto-resolves to the correct shard/cluster) const memberCount = await manager.broadcastEval( (client, ctx) => client.guilds.cache.get(ctx.guildId)?.memberCount, { guildId: '123456789012345678', context: { guildId: '123456789012345678' } }, ); console.log('Member count:', memberCount[0]); ``` ``` -------------------------------- ### Initiate eval from inside a cluster with ClusterClient#broadcastEval Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Similar to ClusterManager#broadcastEval, but initiated from within a cluster process. The request is forwarded to the manager. ```typescript // bot.js const allGuildSizes: number[] = await client.cluster.broadcastEval( c => c.guilds.cache.size, ); console.log('Global guilds:', allGuildSizes.reduce((a, b) => a + b, 0)); // With a timeout to prevent hanging eval const pingResults = await client.cluster.broadcastEval( c => c.ws.ping, { timeout: 5000 }, ); console.log('Pings across clusters:', pingResults); ``` -------------------------------- ### ClusterManager#fetchClientValues Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Fetch a property from all clusters. This is a shorthand for `broadcastEval` when you only need a single dot-separated property path evaluated on each client. ```APIDOC ## ClusterManager#fetchClientValues — Fetch a property from all clusters Shorthand for `broadcastEval` when you only need a single dot-separated property path evaluated on each client. ### Parameters - `path` (string): The dot-separated property path to fetch. - `cluster` (number, optional): The specific cluster to target. If omitted, fetches from all clusters. ### Request Example ```ts // cluster.js const guildSizes: number[] = await manager.fetchClientValues('guilds.cache.size'); console.log('Total guilds:', guildSizes.reduce((a, b) => a + b, 0)); // Target one cluster only const clusterZeroPing = await manager.fetchClientValues('ws.ping', 0); console.log('Cluster 0 WS ping:', clusterZeroPing[0]); ``` ``` -------------------------------- ### ClusterClient#broadcastEval Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Initiate eval from inside a cluster. This method has identical semantics to `ClusterManager#broadcastEval` but is called from within a cluster process. The request is forwarded to the manager, which then fans it out. ```APIDOC ## ClusterClient#broadcastEval — Initiate eval from inside a cluster Identical semantics to `ClusterManager#broadcastEval` but called from within a cluster process. The request is forwarded to the manager, which fans it out. ### Parameters - `func` (Function | string): The function or string to evaluate. - `options` (object, optional): Options for the evaluation. - `timeout` (number, optional): Timeout in milliseconds for the evaluation. ### Request Example ```ts // bot.js const allGuildSizes: number[] = await client.cluster.broadcastEval( c => c.guilds.cache.size, ); console.log('Global guilds:', allGuildSizes.reduce((a, b) => a + b, 0)); // With a timeout to prevent hanging eval const pingResults = await client.cluster.broadcastEval( c => c.ws.ping, { timeout: 5000 }, ); console.log('Pings across clusters:', pingResults); ``` ``` -------------------------------- ### Read Cluster Environment Data with getInfo Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Use getInfo() within a cluster process to access environment data like shard lists, total shard count, and cluster details. This function parses process environment variables or worker data. ```typescript import { getInfo } from 'discord-hybrid-sharding'; const info = getInfo(); console.log(`This process owns shards ${info.FIRST_SHARD_ID}–${info.LAST_SHARD_ID}`); console.log(`Total shards across all clusters: ${info.TOTAL_SHARDS}`); ``` -------------------------------- ### Run code on every cluster with ClusterManager#broadcastEval Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Execute a function or string on each cluster to collect results. Can pass context and target specific clusters or resolve via guild ID. ```typescript // cluster.js — after manager.spawn() // 1. Get guild count from every cluster const guildCounts: number[] = await manager.broadcastEval( (client) => client.guilds.cache.size, ); const total = guildCounts.reduce((a, b) => a + b, 0); console.log(`Total guilds: ${total}`); // 2. Pass context to the function const guildName: string[] = await manager.broadcastEval( (client, ctx) => client.guilds.cache.get(ctx.guildId)?.name ?? null, { context: { guildId: '123456789012345678' } }, ); console.log('Guild name:', guildName.filter(Boolean)[0]); // 3. Target a single cluster const result = await manager.broadcastEval( (client) => client.uptime, { cluster: 2 }, ); console.log('Cluster 2 uptime:', result[0]); // 4. Target by guild ID (auto-resolves to the correct shard/cluster) const memberCount = await manager.broadcastEval( (client, ctx) => client.guilds.cache.get(ctx.guildId)?.memberCount, { guildId: '123456789012345678', context: { guildId: '123456789012345678' } }, ); console.log('Member count:', memberCount[0]); ``` -------------------------------- ### Fetch a property from all clusters with ClusterManager#fetchClientValues Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt A shorthand for broadcastEval to evaluate a single dot-separated property path on each client. Can target a specific cluster by index. ```typescript // cluster.js const guildSizes: number[] = await manager.fetchClientValues('guilds.cache.size'); console.log('Total guilds:', guildSizes.reduce((a, b) => a + b, 0)); // Target one cluster only const clusterZeroPing = await manager.fetchClientValues('ws.ping', 0); console.log('Cluster 0 WS ping:', clusterZeroPing[0]); ``` -------------------------------- ### Manual Cluster Queue Control Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Configures the ClusterManager to disable automatic cluster queuing, allowing for manual control over the spawn process. Requires explicit calls to `manager.queue.next()` or `client.cluster.spawnNextCluster()` to proceed. ```javascript const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 8, shardsPerClusters: 2, queue: { auto: false, }, }); ``` -------------------------------- ### ClusterManager#triggerMaintenance Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Broadcasts a maintenance flag to all or a specific cluster, putting them into maintenance mode. Clusters under maintenance suppress their `ready` event. ```APIDOC ## ClusterManager#triggerMaintenance — Put clusters into maintenance mode Broadcasts a maintenance flag to all (or a specific) cluster. Clusters under maintenance suppress their `ready` event and can be used to hold off event processing during rolling updates. ### Enabling Maintenance: ```ts // cluster.js — enable maintenance on all clusters manager.triggerMaintenance('scheduled-update'); ``` ### Disabling Maintenance: ```ts // cluster.js — disable maintenance by passing undefined/empty string manager.triggerMaintenance(''); ``` ### Checking Maintenance Status within a Cluster: ```ts // bot.js — check maintenance inside the cluster client.once('ready', readyClient => { if (readyClient.cluster.maintenance) { console.log(`Maintenance active: ${readyClient.cluster.maintenance}`); // Skip loading event handlers until maintenance is lifted } readyClient.cluster.triggerReady(); }); ``` ### Toggling Maintenance within a Cluster: ```ts // Cluster can toggle its own maintenance flag client.cluster.triggerMaintenance('local-maintenance'); // enable client.cluster.triggerMaintenance('local-maintenance', true); // enable on ALL clusters ``` ``` -------------------------------- ### Listening to Debug Messages Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Attaches a listener to the 'debug' event on the ClusterManager to log internal debugging information. This is helpful for troubleshooting. ```javascript manager.on('debug', console.log); ``` -------------------------------- ### HeartbeatManager for Auto-Respawning Clusters Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Automatically respawn unresponsive clusters by extending the ClusterManager with HeartbeatManager. Configure the probe interval and the maximum number of missed heartbeats before a respawn. ```typescript import { ClusterManager, HeartbeatManager } from 'discord-hybrid-sharding'; const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 'auto', shardsPerClusters: 2, token: process.env.DISCORD_TOKEN, }); manager.extend( new HeartbeatManager({ interval: 20_000, // probe every 20 s maxMissedHeartbeats: 5, // respawn after 5 missed acks (~100 s of silence) }), ); await manager.spawn({ timeout: -1 }); // manager.heartbeat is now populated with per-cluster Heartbeat instances ``` -------------------------------- ### ReClusterManager for Zero-Downtime Resharding Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Perform zero-downtime resharding or reclustering using ReClusterManager. Supports 'gracefulSwitch' and 'rolling' restart modes. The client-side handles maintenance mode during the transition. ```typescript import { ClusterManager, ReClusterManager } from 'discord-hybrid-sharding'; const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 8, shardsPerClusters: 2, token: process.env.DISCORD_TOKEN, }); manager.extend(new ReClusterManager()); await manager.spawn({ timeout: -1 }); // Later — triggered by a slash command, cron job, or growth threshold: await manager.recluster!.start({ restartMode: 'gracefulSwitch', // or 'rolling' totalShards: 16, // new shard count (or 'auto') shardsPerClusters: 2, delay: 7000, timeout: -1, }); console.log('Zero-downtime reclustering complete'); // bot.js — handle maintenance window on the client side client.cluster.on('ready', () => { // fired when this cluster exits maintenance mode after recluster console.log(`Cluster ${client.cluster.id} is live again`); }); client.once('ready', readyClient => { if (readyClient.cluster.maintenance) { console.log('Cluster starting in maintenance mode, waiting for recluster...'); } readyClient.cluster.triggerReady(); }); ``` -------------------------------- ### Evaluating Script on Manager Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Executes a JavaScript expression on the ClusterManager process and returns the result to the client. Useful for retrieving manager-specific information like memory usage. ```javascript client.cluster.evalOnManager('process.memoryUsage().rss / 1024 ** 2'); ``` -------------------------------- ### Automatic Resharding with AutoResharderManager Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Configure AutoResharderManager to automatically reshard clusters based on guild count. Ensure both ReClusterManager and AutoResharderManager are extended. Set MinGuildsPerShard and MaxGuildsPerShard to define the target and threshold guild counts. ```typescript import { ClusterManager, ReClusterManager, AutoResharderManager, } from 'discord-hybrid-sharding'; const manager = new ClusterManager(`${__dirname}/bot.js`, { totalShards: 'auto', shardsPerClusters: 2, token: process.env.DISCORD_TOKEN, }); manager.extend( new ReClusterManager(), new AutoResharderManager({ ShardsPerCluster: 'useManagerOption', // inherit from ClusterManager MinGuildsPerShard: 1500, // target guilds/shard after reshard MaxGuildsPerShard: 2400, // threshold that triggers reshard restartOptions: { restartMode: 'gracefulSwitch', delay: 7000, timeout: -1, }, debug: true, }), ); await manager.spawn({ timeout: -1 }); ``` ```typescript // bot.js — each cluster reports its guild counts periodically import { AutoResharderClusterClient } from 'discord-hybrid-sharding'; client.cluster = new ClusterClient(client); new AutoResharderClusterClient(client.cluster, { sendDataIntervalMS: 60_000, // report every minute // default sendDataFunction works for discord.js; override for other libs: sendDataFunction: (cluster) => ({ clusterId: cluster.id, shardData: cluster.info.SHARD_LIST.map(shardId => ({ shardId, guildCount: cluster.client.guilds.cache .filter((g: { shardId: number }) => g.shardId === shardId) .size, })), }), }); ``` -------------------------------- ### Broadcast Evaluation with Timeout Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md Performs a broadcast evaluation across all clusters with an optional timeout. If the evaluation does not complete within the specified time, the promise will be rejected. ```javascript client.cluster.broadcastEval('new Promise((resolve, reject) => {})', { timeout: 10000 }); ``` -------------------------------- ### IPC Request/Reply Messaging Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Implement bidirectional, typed request/reply messaging between the manager and clusters. The manager listens for cluster requests and can also initiate requests to clusters. ```typescript import { messageType } from 'discord-hybrid-sharding'; manager.on('clusterCreate', cluster => { cluster.on('message', async message => { if (message._type !== messageType.CUSTOM_REQUEST) return; if (message.action === 'getStats') { await message.reply({ totalGuilds: (await manager.fetchClientValues('guilds.cache.size')) .reduce((a: number, b: number) => a + b, 0), }); } }); // Manager pushes a one-way message to the cluster cluster.send({ content: 'Hello from manager!' }); // Manager sends a request and awaits reply cluster.request({ action: 'ping' }).then(reply => { console.log('Cluster replied:', reply); }); }); // bot.js — cluster handles incoming messages and sends requests client.cluster.on('message', async message => { if (message._type !== messageType.CUSTOM_REQUEST) return; if (message.action === 'ping') { await message.reply({ pong: true, uptime: process.uptime() }); } }); // Cluster initiates a request to the manager const stats = await client.cluster.request({ action: 'getStats' }); console.log('Total guilds reported by manager:', stats.totalGuilds); ``` -------------------------------- ### AutoResharderManager Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Automatically triggers a zero-downtime reshard when any shard exceeds MaxGuildsPerShard. Requires both ReClusterManager and AutoResharderManager to be registered via manager.extend(). ```APIDOC ## AutoResharderManager Automatically triggers a zero-downtime reshard when any shard exceeds `MaxGuildsPerShard`. Requires both `ReClusterManager` and `AutoResharderManager` to be registered via `manager.extend()`. ### Configuration Options: - `ShardsPerCluster`: Inherits from `ClusterManager` if set to 'useManagerOption'. - `MinGuildsPerShard`: The target number of guilds per shard after resharding. - `MaxGuildsPerShard`: The threshold that triggers a reshard. - `restartOptions`: Configuration for cluster restarts (e.g., `restartMode`, `delay`, `timeout`). - `debug`: Enables debug logging. ### Usage Example: ```ts import { ClusterManager, ReClusterManager, AutoResharderManager, } from 'discord-hybrid-sharding'; const manager = new ClusterManager('./bot.js', { totalShards: 'auto', shardsPerClusters: 2, token: process.env.DISCORD_TOKEN, }); manager.extend( new ReClusterManager(), new AutoResharderManager({ ShardsPerCluster: 'useManagerOption', MinGuildsPerShard: 1500, MaxGuildsPerShard: 2400, restartOptions: { restartMode: 'gracefulSwitch', delay: 7000, timeout: -1, }, debug: true, }), ); await manager.spawn({ timeout: -1 }); ``` ### Cluster-side Reporting: ```ts // bot.js — each cluster reports its guild counts periodically import { AutoResharderClusterClient } from 'discord-hybrid-sharding'; client.cluster = new ClusterClient(client); new AutoResharderClusterClient(client.cluster, { sendDataIntervalMS: 60_000, sendDataFunction: (cluster) => ({ clusterId: cluster.id, shardData: cluster.info.SHARD_LIST.map(shardId => ({ shardId, guildCount: cluster.client.guilds.cache .filter((g: { shardId: number }) => g.shardId === shardId) .size, })), }), }); ``` ``` -------------------------------- ### Bind AutoResharderClusterClient Source: https://github.com/meister03/discord-hybrid-sharding/blob/ts-rewrite/README.md This code snippet shows how to bind the AutoResharderClusterClient to a Discord.js client. It allows for custom data sending intervals and functions. ```typescript client.cluster = new ClusterManager(client); new AutoResharderClusterClient(client.cluster, { sendDataIntervalMS: 60e3, sendDataFunction: (cluster:ClusterClient) => { return { clusterId: cluster.id, shardData: cluster.info.SHARD_LIST.map(shardId => ({ shardId, guildCount: cluster.client.guildsche.filter(g => g.shardId === shardId).size })) } } }); ``` -------------------------------- ### Evaluate code on the manager process with ClusterManager#evalOnManager Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Executes an expression in the manager's Node.js context, returning the result. Useful for inspecting or mutating manager-level state from a cluster. ```typescript // cluster.js — direct call const uptime = await manager.evalOnManager('process.uptime'); console.log('Manager uptime (s):', uptime._result); // bot.js — called from inside a cluster const result = await client.cluster.evalOnManager( (mgr) => ({ totalClusters: mgr.totalClusters, totalShards: mgr.totalShards, }), ); console.log('Manager stats:', result); ``` -------------------------------- ### ClusterManager#evalOnManager Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Evaluate code on the manager process. This method runs an expression in the manager's own Node.js context and returns the result. It is useful for inspecting or mutating manager-level state from a cluster. ```APIDOC ## ClusterManager#evalOnManager — Evaluate code on the manager process Runs an expression in the manager's own Node.js context and returns the result. Useful for inspecting or mutating manager-level state from a cluster. ### Parameters - `func` (Function | string): The function or string to evaluate. ### Request Example ```ts // cluster.js — direct call const uptime = await manager.evalOnManager('process.uptime'); console.log('Manager uptime (s):', uptime._result); // bot.js — called from inside a cluster const result = await client.cluster.evalOnManager( (mgr) => ({ totalClusters: mgr.totalClusters, totalShards: mgr.totalShards, }), ); console.log('Manager stats:', result); ``` ``` -------------------------------- ### Cluster Maintenance Mode Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Utilize `ClusterManager#triggerMaintenance` to put clusters into a maintenance mode, suppressing their `ready` event and holding off event processing. This is useful for rolling updates. Pass an empty string or undefined to disable maintenance. ```typescript // cluster.js — enable maintenance on all clusters manager.triggerMaintenance('scheduled-update'); // cluster.js — disable maintenance by passing undefined/empty string manager.triggerMaintenance(''); // bot.js — check maintenance inside the cluster client.once('ready', readyClient => { if (readyClient.cluster.maintenance) { console.log(`Maintenance active: ${readyClient.cluster.maintenance}`); // Skip loading event handlers until maintenance is lifted } readyClient.cluster.triggerReady(); }); // Cluster can toggle its own maintenance flag client.cluster.triggerMaintenance('local-maintenance'); // enable client.cluster.triggerMaintenance('local-maintenance', true); // enable on ALL clusters ``` -------------------------------- ### shardIdForGuildId Source: https://context7.com/meister03/discord-hybrid-sharding/llms.txt Utility function to resolve which shard owns a given guild ID using Discord's sharding formula. ```APIDOC ## shardIdForGuildId — Resolve which shard owns a guild Utility that converts a Discord snowflake guild ID to the internal shard ID responsible for it, following Discord's formula `(guildId >> 22) % totalShards`. ### Usage: ```ts import { shardIdForGuildId } from 'discord-hybrid-sharding'; const guildId = '123456789012345678'; const totalShards = 16; const shardId = shardIdForGuildId(guildId, totalShards); console.log(`Guild ${guildId} is on shard ${shardId}`); // => Guild 123456789012345678 is on shard 3 ``` ### Usage with `broadcastEval`: ```ts // Use it with broadcastEval to target the right cluster const memberCount = await manager.broadcastEval( (client, ctx) => client.guilds.cache.get(ctx.guildId)?.memberCount ?? null, { guildId, context: { guildId } }, // manager resolves guildId → shard → cluster automatically ); console.log('Member count:', memberCount[0]); ``` ```