{"id":20510629,"url":"https://github.com/danclay/eris-fleet","last_synced_at":"2025-07-21T12:34:18.361Z","repository":{"id":38462643,"uuid":"266729143","full_name":"danclay/eris-fleet","owner":"danclay","description":"Cluster management for Discord bots using the Eris library.","archived":false,"fork":false,"pushed_at":"2024-08-30T13:24:31.000Z","size":1276,"stargazers_count":40,"open_issues_count":6,"forks_count":18,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T15:35:34.045Z","etag":null,"topics":["bot","clustering","discord","eris","nodejs","sharding"],"latest_commit_sha":null,"homepage":"https://danclay.github.io/eris-fleet","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danclay.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-25T08:46:34.000Z","updated_at":"2025-01-15T01:30:36.000Z","dependencies_parsed_at":"2024-01-15T04:56:25.605Z","dependency_job_id":"764e38cd-6a90-48af-a800-db1a5390993c","html_url":"https://github.com/danclay/eris-fleet","commit_stats":{"total_commits":169,"total_committers":7,"mean_commits":"24.142857142857142","dds":"0.17159763313609466","last_synced_commit":"af743fa3a0146ecb79a434d2c569ed0f734511bc"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/danclay/eris-fleet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danclay%2Feris-fleet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danclay%2Feris-fleet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danclay%2Feris-fleet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danclay%2Feris-fleet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danclay","download_url":"https://codeload.github.com/danclay/eris-fleet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danclay%2Feris-fleet/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266302934,"owners_count":23908265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","clustering","discord","eris","nodejs","sharding"],"created_at":"2024-11-15T20:30:13.861Z","updated_at":"2025-07-21T12:34:18.252Z","avatar_url":"https://github.com/danclay.png","language":"TypeScript","funding_links":[],"categories":["Libraries"],"sub_categories":["JavaScript"],"readme":"**⚠️ This repo will no longer be updated since eris-fleet has been moved to a monorepo to make adaptation of it for the [Oceanic library](https://github.com/OceanicJS/Oceanic) easier. This monorepo is  [wumpus-navy](https://github.com/danclay/wumpus-navy). For the latest version see the monorepo. Eris-fleet the package is not deprecated and the npm package will be updated under the same name as before. This repo is deprecated.**\n\n**The documentation has moved as well: [https://danclay.github.io/wumpus-navy/](https://danclay.github.io/wumpus-navy/)**\n\n\u003cdiv align=\"center\"\u003e\n  \u003cp\u003e\n  \u003ca href=\"https://github.com/abalabahaha/eris\"\u003e\u003cimg src=\"https://img.shields.io/badge/Discord%20Library-Eris-blue?style=flat-square\" alt=\"Discord Library\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/eris-fleet\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/eris-fleet.svg?cacheSeconds=3600\u0026style=flat-square\u0026label=version\u0026logo=npm\" alt=\"NPM version\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://raw.githubusercontent.com/danclay/eris-fleet/master/LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/npm/l/eris-fleet?style=flat-square\"\u003e\n    \u003ca href=\"https://github.com/danclay/eris-fleet/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/workflow/status/danclay/eris-fleet/Node.js%20CI/master?style=flat-square\u0026logo=github\" alt=\"Node.js CI\" /\u003e\u003c/a\u003e\n  \u003c/p\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://www.npmjs.com/package/eris-fleet/\"\u003e\u003cimg src=\"https://nodeico.herokuapp.com/eris-fleet.svg\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n### [Documentation](https://danclay.github.io/eris-fleet/) | [Eris](https://github.com/abalabahaha/eris)\n\n# About eris-fleet\n\nA spin-off of [eris-sharder](https://github.com/discordware/eris-sharder) and [megane](https://github.com/brussell98/megane) with services and configurable logging.\n\nFor detailed documentation check the [docs](https://danclay.github.io/eris-fleet/).\n\neris-fleet currently supports Eris v0.16.x.\n\n## Highlighted Features:\n\n- Clustering across cores\n- Sharding\n- Recalculate shards with minimal downtime\n- Update a bot with minimal downtime using soft restarts\n- Customizable logging\n- Fetch data from across clusters easily\n- Services (non-eris workers)\n- IPC to communicate between clusters, other clusters, and services\n- Detailed stats collection\n- Soft cluster and service restarts where the old worker is killed after the new one is ready\n- Graceful shutdowns\n- Central request handler\n- Central data store\n- Can use a modified version of Eris\n- Concurrency support\n\nA very basic diagram:\n\n![Basic diagram](https://cdn.discordapp.com/attachments/866590047436144641/965161462479859742/Untitled_Diagram.drawio_1.png)\n\n## Help\n\nIf you still have questions, you can join the support server on Discord: [Discord server](https://discord.gg/tk2n3naJn3)\n\n[![Support server on Discord](https://discord.com/api/guilds/866589508392976384/widget.png?style=banner2)](https://discord.gg/tk2n3naJn3)\n\n# Installation\nRun `npm install eris-fleet` or with yarn: `yarn add eris-fleet`.\n\nTo use a less refined, but more up-to-date branch, use `npm install danclay/eris-fleet#dev` or `yarn add danclay/eris-fleet#dev`. [Documentation for the dev branch.](https://github.com/danclay/eris-fleet/tree/dev)\n\n# Basics\n\nSome working examples are in [test/](https://github.com/danclay/eris-fleet/tree/master/test).\n\n## Naming Conventions\n| Term | Description |\n|-----------|----------------------------------------------------------------------------|\n| \"fleet\" | All the components below |\n| \"admiral\" | A single sharding manager |\n| \"worker\" | A worker for node clustering |\n| \"cluster\" | A worker containing Eris shards |\n| \"service\" | A worker that does not contain Eris shards, but can interact with clusters |\n\n## Get Started\nTo get started, you will need at least 2 files:\n1. Your file which will create the fleet. This will be called \"index.js\" for now.\n2. Your file containing your bot code. This will be called \"bot.js\" for now. This file will extend `BaseClusterWorker`\n\nIn the example below, the variable `options` is passed to the admiral. [Read the docs](https://danclay.github.io/eris-fleet/interfaces/Options.html) for what options you can pass.\n\nHere is an example of `index.js`:\n```js\nconst { isMaster } = require('cluster');\nconst { Fleet } = require('eris-fleet');\nconst path = require('path');\nconst { inspect } = require('util');\n\nrequire('dotenv').config();\n\nconst options = {\n    path: path.join(__dirname, \"./bot.js\"),\n    token: process.env.token\n}\n\nconst Admiral = new Fleet(options);\n\nif (isMaster) {\n    // Code to only run for your master process\n    Admiral.on('log', m =\u003e console.log(m));\n    Admiral.on('debug', m =\u003e console.debug(m));\n    Admiral.on('warn', m =\u003e console.warn(m));\n    Admiral.on('error', m =\u003e console.error(inspect(m)));\n\n    // Logs stats when they arrive\n    Admiral.on('stats', m =\u003e console.log(m));\n}\n```\nThis creates a new Admiral that will manage `bot.js` running in other processes. [More details](https://danclay.github.io/eris-fleet/classes/BaseClusterWorker.html)\n\nThe following is an example of `bot.js`. [Read the IPC docs](https://danclay.github.io/eris-fleet/classes/IPC.html) for what you can access and do with clusters.\n```js\nconst { BaseClusterWorker } = require('eris-fleet');\n\nmodule.exports = class BotWorker extends BaseClusterWorker {\n    constructor(setup) {\n        // Do not delete this super.\n        super(setup);\n\n        this.bot.on('messageCreate', this.handleMessage.bind(this));\n\n        // Demonstration of the properties the cluster has (Keep reading for info on IPC):\n        this.ipc.log(this.workerID); // ID of the worker\n        this.ipc.log(this.clusterID); // The ID of the cluster\n    }\n\n    async handleMessage(msg) {\n        if (msg.content === \"!ping\" \u0026\u0026 !msg.author.bot) {\n            this.bot.createMessage(msg.channel.id, \"Pong!\");\n        }\n    }\n\n\thandleCommand(dataSentInCommand) {\n\t\t// Optional function to return data from this cluster when requested\n\t\treturn \"hello!\"\n\t}\n\n    shutdown(done) {\n        // Optional function to gracefully shutdown things if you need to.\n        done(); // Use this function when you are done gracefully shutting down.\n    }\n}\n```\n**Make sure your bot file extends BaseClusterWorker!**\nThe bot above will respond with \"Pong!\" when it receives the command \"!ping\".\n\n## Services\n\nYou can create services for your bot. Services are workers which do not interact directly with Eris. Services are useful for processing tasks, a central location to get the latest version of languages for your bot, custom statistics, and more! [Read the IPC docs](https://danclay.github.io/eris-fleet/classes/IPC.html) for what you can access and do with services. **Note that services always start before the clusters. Clusters will only start after all the services have started.** [More details](https://danclay.github.io/eris-fleet/classes/BaseServiceWorker.html)\n\nTo add a service, add the following to the options you pass to the fleet:\n\n```js\nconst options = {\n    // Your other options...\n    services: [{name: \"myService\", path: path.join(__dirname, \"./service.js\")}]\n}\n```\nAdd a new array element for each service you want to register. Make sure each service has a unique name or else the fleet will crash.\n\nHere is an example of `service.js`:\n\n```js\nconst { BaseServiceWorker } = require('eris-fleet');\n\nmodule.exports = class ServiceWorker extends BaseServiceWorker {\n    constructor(setup) {\n        // Do not delete this super.\n        super(setup);\n\n        // Run this function when your service is ready for use. This MUST be run for the worker spawning to continue.\n        this.serviceReady();\n\n        // Demonstration of the properties the service has (Keep reading for info on IPC):\n    \tthis.ipc.log(this.workerID); // ID of the worker\n    \tthis.ipc.log(this.serviceName); // The name of the service\n\n    }\n    // This is the function which will handle commands\n    async handleCommand(dataSentInCommand) {\n        // Return a response if you want to respond\n        return dataSentInCommand.smileyFace;\n    }\n\n    shutdown(done) {\n        // Optional function to gracefully shutdown things if you need to.\n        done(); // Use this function when you are done gracefully shutting down.\n    }\n}\n```\n\n**Make sure your service file extends BaseServiceWorker!**\nThis service will simply return a value within an object sent to it within the command message called \"smileyFace\". Services can be used for much more than this though. To send a command to this service, you could use this:\n\n```js\nconst reply = await this.ipc.command(\"myService\", {smileyFace: \":)\"}, true);\nthis.bot.createMessage(msg.channel.id, reply);\n```\n\nThis command is being sent using the IPC. In this command, the first argument is the name of the service to send the command to, the second argument is the message to send it (in this case a simple object), and the third argument is whether you want a response (this will default to false unless you specify \"true\"). If you want a response, you must `await` the command or use `.then()`.\n\n### Handling service errors\n\nIf you encounter an error while starting your service, run `this.serviceStartingError('error here')` instead of `this.serviceReady()`. Using this will report an error and restart the worker. **Note that services always start before the clusters, so if your service keeps having starting errors your bot will be stuck in a loop.** This issue may be fixed in the future from some sort of maxRestarts option, but this is currently not a functionality.\n\nIf you encounter an error when processing a command within your service, you can do the following to reject the promise:\n```js\n// handleCommand function within the ServiceWorker class\nasync handleCommand(dataSentInCommand) {\n    // Rejects the promise\n    return {err: \"Uh oh.. an error!\"};\n}\n```\nWhen sending the command, you can do the following to deal with the error:\n```js\nthis.ipc.command(\"myService\", {smileyFace: \":)\"}, true).then((reply) =\u003e {\n    // A successful response\n    this.bot.createMessage(msg.channel.id, reply);\n}).catch((e) =\u003e {\n    // Do whatever you want with the error\n    console.error(e);\n});\n```\n\n# In-depth\n\nBelow is more in-depth documentation.\n\n## Admiral \n\n### Admiral options\n\nVisit [the docs](https://danclay.github.io/eris-fleet/interfaces/Options.html) for a complete list of options.\n\n### Admiral events\n\nVisit [the docs](https://danclay.github.io/eris-fleet/classes/Fleet.html) for a complete list of events.\n\n### Central Request Handler\n\nThe central request handler forwards Eris requests to the master process where the request is sent to a single Eris request handler instance. This helps to prevent 429 errors from occurring when you have x number of clusters keeping track of ratelimiting separately. When a response is received, it is sent back to the cluster's Eris client.\n\n### Large Bots\n\nIf you are using a \"very large bot,\" Discord's special gateway settings apply. Ensure your shard count is a multiple of the number set by Discord or set `options.shards` and `options.guildsPerShard` to `\"auto\"`. You may also be able to use concurrency (see below).\n\n### Concurrency\n\nEris-fleet supports concurrency by starting clusters at the same time based on your bot's `max_concurrency` value. The clusters are started together in groups. The `max_concurrency` value can be overridden with [options.maxConcurrencyOverride](https://danclay.github.io/eris-fleet/interfaces/Options.html#maxConcurrencyOverride)\n\n### Formats\n\nVisit [the docs](https://danclay.github.io/eris-fleet/modules.html) to view the Typescript interfaces.\n\n### Choose what to log\n\nYou can choose what to log by using the `whatToLog` property in the options object. You can choose either a whitelist or a blacklist of what to log. You can select what to log by using an array. To possible array elements are shown [on the docs](https://danclay.github.io/eris-fleet/modules.html#LoggingOptions). Here is an example of choosing what to log:\n```js\nconst options = {\n    // Your other options\n    whatToLog: {\n        // This will only log when the admiral starts, when clusters are ready, and when services are ready.\n        whitelist: ['admiral_start', 'cluster_ready', 'service_ready']\n    }\n};\n```\nChange `whitelist` to `blacklist` if you want to use a blacklist. Change the array as you wish. **Errors and warnings will always be sent.**\n\n## IPC\n\nClusters and services can use IPC to interact with other clusters, the Admiral, and services. Visit [the IPC docs](https://danclay.github.io/eris-fleet/classes/IPC.html) to view available methods.\n\n## Stats\n\nStats are given in [this](https://danclay.github.io/eris-fleet/interfaces/Stats.html) format.\n\n## Using a specific version of Eris or a modified version of Eris\n\nYou can use an extended Eris client by passing it to the Options. (see the [options.customClient](https://danclay.github.io/eris-fleet/interfaces/Options.html#customClient) section).\n\nEris-fleet is able to use packages such as eris-additions if you desire. To do so, modify your bot file to match the following template:\n```js\n// Example using eris-additions\nconst { Fleet } = require(\"eris-fleet\");\nconst Eris = require(\"eris-additions\")(require(\"eris\"));\n\nconst options = {\n    // other options\n    customClient: Eris\n}\nconst Admiral = new Fleet(options);\n```\n\n## Using ES Modules\n\nInstead of using the file path, you can use ES Modules by passing your BotWorker class to `options.BotWorker` and your ServiceWorker class to `ServiceWorker` in the `options.services` array. See [test/](https://github.com/danclay/eris-fleet/tree/master/test) for examples.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanclay%2Feris-fleet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanclay%2Feris-fleet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanclay%2Feris-fleet/lists"}