{"version":3,"file":"index.cjs","names":["Server","Client"],"sources":["../src/bridge/BridgeClusterConnection.ts","../src/general/EventManager.ts","../src/bridge/BridgeInstanceConnection.ts","../src/bridge/ClusterCalculator.ts","../src/general/ShardingUtil.ts","../src/bridge/Bridge.ts","../src/cluster/Cluster.ts","../src/cluster/ClusterProcess.ts","../src/instance/BotInstance.ts","../src/instance/ManagedInstance.ts","../src/instance/StandaloneInstance.ts"],"sourcesContent":["import {BridgeInstanceConnection} from \"./BridgeInstanceConnection\";\n\nexport enum BridgeClusterConnectionStatus {\n    REQUESTING = 'requesting',\n    STARTING = 'starting',\n    CONNECTED = 'connected',\n    RECLUSTERING = 'reclustering',\n    DISCONNECTED = 'disconnected',\n}\n\nexport class BridgeClusterConnection {\n    public readonly clusterID: number;\n    public readonly shardList: number[];\n    public connectionStatus: BridgeClusterConnectionStatus = BridgeClusterConnectionStatus.DISCONNECTED;\n\n    public connection?: BridgeInstanceConnection;\n\n    public oldConnection?: BridgeInstanceConnection;\n\n    public missedHeartbeats: number = 0;\n\n    public heartbeatResponse?: HeartbeatResponse;\n\n    public heartbeatPending = false;\n\n    public readyAt?: number;\n\n    public spawnedAt?: number;\n\n    constructor(clusterID: number, shardList: number[]) {\n        this.clusterID = clusterID;\n        this.shardList = shardList;\n    }\n\n    setConnection(connection?: BridgeInstanceConnection): void {\n        if(connection == undefined){\n            this.connectionStatus = BridgeClusterConnectionStatus.DISCONNECTED;\n            this.connection = undefined;\n            return;\n        }\n\n        if (this.connection) {\n            throw new Error(`Connection already set for cluster ${this.clusterID}`);\n        }\n\n        this.connectionStatus = BridgeClusterConnectionStatus.REQUESTING;\n        this.connection = connection;\n    }\n\n    setOldConnection(connection?: BridgeInstanceConnection): void {\n        this.oldConnection = connection;\n    }\n\n    isUsed(): boolean {\n        return this.connection != undefined && this.connectionStatus !== BridgeClusterConnectionStatus.DISCONNECTED;\n    }\n\n    reclustering(connection: BridgeInstanceConnection): void {\n        this.connectionStatus = BridgeClusterConnectionStatus.RECLUSTERING;\n        this.oldConnection = this.connection;\n        this.connection = connection;\n    }\n\n    addMissedHeartbeat(): void {\n        this.missedHeartbeats++;\n    }\n\n    removeMissedHeartbeat(): void {\n        if (this.missedHeartbeats > 0) {\n            this.missedHeartbeats--;\n        }\n    }\n\n    resetMissedHeartbeats(): void {\n        this.missedHeartbeats = 0;\n    }\n}\n\nexport type HeartbeatResponse = {\n    cpu: {\n        raw: {\n            user: number,\n            system: number,\n        }\n        cpuPercent: string\n    },\n    memory: {\n        raw: {\n            rss: number,\n            heapTotal: number,\n            heapUsed: number,\n            external: number,\n            arrayBuffers: number,\n        },\n        memoryPercent: string\n        usage: number\n    },\n    ping: number,\n    shardPings: {\n        id: number,\n        ping: number,\n        status: number,\n        guilds: number,\n        members: number\n    }[]\n}","import {EventPayload} from \"./EventPayload\";\n\nexport class EventManager {\n\n    private pendingPayloads = new Map<string, {\n        resolve: (value: unknown) => void;\n        reject: (error: unknown) => void;\n    }>();\n\n    // Track per-request timeout handles so we can clear them on resolve/reject\n    private pendingTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\n    private readonly _send: (payload: EventPayload) => Promise<void>;\n\n    private readonly _on: (payload: unknown) => void;\n\n    private readonly _request: (payload: unknown) => unknown;\n\n    constructor(send: (payload: EventPayload) => Promise<void>, on: (message: unknown) => void, request: (message: unknown) => unknown) {\n        this._send = send;\n        this._on = on;\n        this._request = request\n    }\n\n    async send(data: unknown) {\n        return this._send({\n            id: crypto.randomUUID(),\n            type: 'message',\n            data: data\n        });\n    }\n\n    async request<T>(payload: unknown, timeout: number): Promise<T> {\n        const id = crypto.randomUUID();\n\n        return new Promise<T>((resolve, reject) => {\n            this.pendingPayloads.set(id, {\n                resolve: resolve as (value: unknown) => void,\n                reject\n            });\n\n            const t = setTimeout(() => {\n                if (this.pendingPayloads.has(id)) {\n                    this.pendingPayloads.delete(id);\n                    this.pendingTimeouts.delete(id);\n                    reject({\n                        error: `Request with id ${id} timed out`,\n                    });\n                }\n            }, timeout);\n            this.pendingTimeouts.set(id, t);\n\n            this._send({\n                id: id,\n                type: 'request',\n                data: payload\n            }).catch((err) => {\n                if (this.pendingPayloads.has(id)) {\n                    const to = this.pendingTimeouts.get(id);\n                    if (to) clearTimeout(to);\n                    this.pendingTimeouts.delete(id);\n                    this.pendingPayloads.delete(id);\n                    reject(err);\n                }\n            });\n        })\n    }\n\n    receive(possiblePayload: unknown) {\n        if (typeof possiblePayload !== 'object' || possiblePayload === null) {\n            return;\n        }\n\n        const payload = possiblePayload as EventPayload;\n\n        if (!payload.id || !payload.type) {\n            return;\n        }\n\n        if (payload.type === 'message') {\n            this._on(payload.data);\n            return;\n        }\n\n        if (payload.type === 'response') {\n            // Handle requests\n            const resolve = this.pendingPayloads.get(payload.id)?.resolve;\n            if (resolve) {\n                resolve(payload.data);\n                this.pendingPayloads.delete(payload.id);\n                const to = this.pendingTimeouts.get(payload.id);\n                if (to) clearTimeout(to);\n                this.pendingTimeouts.delete(payload.id);\n            }\n            return;\n        }\n\n        if (payload.type === 'response_error') {\n            // Handle requests\n            const reject = this.pendingPayloads.get(payload.id)?.reject;\n            if (reject) {\n                reject(payload.data);\n                this.pendingPayloads.delete(payload.id);\n                const to = this.pendingTimeouts.get(payload.id);\n                if (to) clearTimeout(to);\n                this.pendingTimeouts.delete(payload.id);\n            }\n            return;\n        }\n\n        if (payload.type === 'request') {\n            // Handle requests\n            const data = this._request(payload.data);\n            if(data instanceof Promise) {\n                data.then((result) => {\n                    this._send({\n                        id: payload.id,\n                        type: 'response',\n                        data: result\n                    }).catch(() => {});\n                }).catch((error) => {\n                    this._send({\n                        id: payload.id,\n                        type: 'response_error',\n                        data: error\n                    }).catch(() => {});\n                });\n            } else {\n                this._send({\n                    id: payload.id,\n                    type: 'response',\n                    data: data\n                }).catch(() => {});\n            }\n            return;\n        }\n    }\n\n    // Reject and clear all pending requests to avoid memory leaks when a connection/process closes\n    close(reason?: string) {\n        if (this.pendingPayloads.size === 0 && this.pendingTimeouts.size === 0) return;\n        const err = { error: reason || 'EventManager closed' };\n        for (const [id, handlers] of this.pendingPayloads.entries()) {\n            try { handlers.reject(err); } catch (_) { /* ignore */ }\n            this.pendingPayloads.delete(id);\n            const to = this.pendingTimeouts.get(id);\n            if (to) clearTimeout(to);\n            this.pendingTimeouts.delete(id);\n        }\n        // In case there are any stray timeouts with no pending payload\n        for (const to of this.pendingTimeouts.values()) {\n            clearTimeout(to);\n        }\n        this.pendingTimeouts.clear();\n    }\n}\n\n","import {EventManager} from \"../general/EventManager\";\nimport {Connection} from \"net-ipc\";\n\nexport enum BridgeInstanceConnectionStatus {\n    READY = 'ready',\n    PENDING_STOP = 'pending_stop',\n}\nexport class BridgeInstanceConnection {\n    public readonly instanceID: number;\n    public readonly eventManager: EventManager;\n    public readonly connection: Connection;\n    public readonly data: unknown;\n    public connectionStatus: BridgeInstanceConnectionStatus = BridgeInstanceConnectionStatus.READY;\n    public readonly dev: boolean = false;\n    public readonly establishedAt: number = Date.now();\n\n    private _onMessage?: (message: unknown) => void;\n    private _onRequest?: (message: unknown) => unknown;\n\n    constructor(instanceID: number, connection: Connection, data: unknown, dev: boolean) {\n        this.instanceID = instanceID;\n        this.connection = connection;\n        this.data = data;\n        this.dev = dev || false;\n        this.eventManager = new EventManager((message) => {\n            if(!this.connection?.connection?.closed){\n                return this.connection.send(message);\n            }\n            return Promise.reject(new Error('Connection is closed, cannot send message'));\n        }, (message) => {\n            if (this._onMessage) {\n                this._onMessage(message);\n            }\n        }, (message) => {\n            if (this._onRequest) {\n                return this._onRequest(message);\n            }\n            return undefined;\n        })\n    }\n\n    messageReceive(message: any) {\n        this.eventManager.receive(message);\n    }\n\n    onRequest(callback: (message: unknown) => unknown) {\n        this._onRequest = callback;\n    }\n\n    onMessage(callback: (message: unknown) => void) {\n        this._onMessage = callback;\n    }\n}","import {BridgeClusterConnection, BridgeClusterConnectionStatus} from \"./BridgeClusterConnection\";\nimport {BridgeInstanceConnection, BridgeInstanceConnectionStatus} from \"./BridgeInstanceConnection\";\n\n/**\n * Manages the calculation and distribution of clusters for a Discord bot sharding system.\n * This class is responsible for creating clusters with their assigned shards,\n * tracking which clusters are in use, and providing methods to retrieve available clusters.\n */\nexport class ClusterCalculator {\n    /** The total number of clusters to initialize */\n    private readonly clusterToStart: number;\n\n    /** The number of shards that each cluster will manage */\n    private readonly shardsPerCluster: number;\n\n    /** List of all clusters managed by this calculator */\n    public readonly clusterList: BridgeClusterConnection[]= [];\n\n    /**\n     * Creates a new ClusterCalculator and initializes the clusters.\n     * \n     * @param clusterToStart - The number of clusters to create\n     * @param shardsPerCluster - The number of shards each cluster will manage\n     */\n    constructor(clusterToStart: number, shardsPerCluster: number) {\n        this.shardsPerCluster = shardsPerCluster;\n        this.clusterToStart = clusterToStart;\n\n        this.calculateClusters();\n    }\n\n    /**\n     * Calculates and initializes all clusters with their assigned shards.\n     * Each cluster is assigned a sequential range of shard IDs based on its cluster index.\n     */\n    private calculateClusters(): void {\n        const clusters: Map<number, number[]> = new Map();\n        for (let i = 0; i < this.clusterToStart; i++) {\n            clusters.set(i, []);\n            for (let j = 0; j < this.shardsPerCluster; j++) {\n                clusters.get(i)?.push(i * this.shardsPerCluster + j);\n            }\n        }\n\n        for (let [clusterIndex, clusterShards] of clusters.entries()) {\n            this.clusterList.push(new BridgeClusterConnection(clusterIndex, clusterShards));\n        }\n    }\n\n    /**\n     * Retrieves the next available (unused) cluster and marks it as used.\n     * \n     * @returns The next available cluster, or undefined if all clusters are in use\n     */\n    public getNextCluster(): BridgeClusterConnection | undefined {\n        for (const cluster of this.clusterList) {\n            if (!cluster.isUsed()) {\n                return cluster;\n            }\n        }\n        return undefined; // No available clusters\n    }\n\n    /**\n     * Retrieves multiple available clusters up to the specified count.\n     * Each returned cluster is marked as used.\n     * \n     * @param count - The maximum number of clusters to retrieve\n     * @returns An array of available clusters (may be fewer than requested if not enough are available)\n     */\n    public getNextClusters(count: number): BridgeClusterConnection[] {\n        const availableClusters: BridgeClusterConnection[] = [];\n        for (const cluster of this.clusterList) {\n            if (!cluster.isUsed() && availableClusters.length < count) {\n                availableClusters.push(cluster);\n            }\n        }\n        return availableClusters; // Returns the clusters that were found\n    }\n\n    /**\n     * Sets the used status of a specific cluster by its ID.\n     *\n     * @param clusterID - The ID of the cluster to update\n     * @param connection - The connection to associate with the cluster\n     */\n    public clearClusterConnection(clusterID: number): void {\n        const cluster = this.clusterList.find(c => c.clusterID === clusterID);\n        if (cluster) {\n            cluster.setConnection(undefined);\n        }\n    }\n\n    public getClusterForConnection(connection: BridgeInstanceConnection): BridgeClusterConnection[] {\n        return this.clusterList.filter(cluster =>\n            cluster.connection?.instanceID === connection.instanceID\n        );\n    }\n\n    public getOldClusterForConnection(connection: BridgeInstanceConnection): BridgeClusterConnection[] {\n        return this.clusterList.filter(cluster =>\n            cluster.oldConnection?.instanceID === connection.instanceID\n        );\n    }\n\n    public checkAllClustersConnected(): boolean {\n        for (const cluster of this.clusterList) {\n            if (cluster.connectionStatus != BridgeClusterConnectionStatus.CONNECTED){\n                return false; // At least one cluster is not in use\n            }\n        }\n        return true; // All clusters are in use\n    }\n\n\n    findMostAndLeastClustersForConnections(\n        connectedClients: BridgeInstanceConnection[]\n    ): {\n        most: BridgeInstanceConnection | undefined,\n        least: BridgeInstanceConnection | undefined\n    } {\n\n        const openClients = connectedClients.filter(x => !x.dev)\n\n        const devClients = connectedClients.filter(x => x.dev)\n        const summDevConnectedClusters = devClients.map(c => this.getClusterForConnection(c).length).reduce((a, b) => a + b, 0);\n\n        let most: BridgeInstanceConnection | undefined;\n        let least: BridgeInstanceConnection | undefined;\n        let remainder = ((this.clusterToStart - summDevConnectedClusters) % openClients.length || 0);\n\n        for (const client of openClients) {\n            const clusters = this.getClusterForConnection(client);\n\n            if (!most || clusters.length > this.getClusterForConnection(most).length) {\n                most = client;\n            }\n\n            if (!least || clusters.length < this.getClusterForConnection(least).length) {\n                least = client;\n            }\n        }\n\n        if (most && least) {\n            const mostCount = this.getClusterForConnection(most).length;\n            const leastCount = this.getClusterForConnection(least).length;\n\n            // Only recluster if the difference is greater than remainder\n            if (mostCount - leastCount <= remainder) {\n                return {most: undefined, least: undefined};\n            }\n        }\n\n        return {most, least};\n    }\n\n    getClusterWithLowestLoad(connectedClients: Map<string, BridgeInstanceConnection>): BridgeInstanceConnection | undefined {\n        let lowestLoadClient: BridgeInstanceConnection | undefined;\n        let lowestLoad = Infinity;\n\n        for (const client of connectedClients.values().filter(c =>\n            c.connectionStatus === BridgeInstanceConnectionStatus.READY && !c.dev)) {\n            const clusters = this.getClusterForConnection(client);\n\n            const load = clusters.length; // Assuming load is determined by the number of clusters assigned\n            if (load < lowestLoad) {\n                lowestLoad = load;\n                lowestLoadClient = client;\n            }\n        }\n\n        return lowestLoadClient; // Returns the client with the lowest load, or undefined if no clients are connected\n    }\n\n    getClusterOfShard(shardID: number) {\n        return this.clusterList.find(c => c.shardList.includes(shardID));\n    }\n}\n","export class ShardingUtil {\n    public static getShardIDForGuild(guildID: string, totalShards: number): number {\n        if (!guildID || totalShards <= 0) {\n            throw new Error(\"Invalid guild ID or total shards\");\n        }\n\n        return  Number(BigInt(guildID) >> 22n) % totalShards;\n    }\n}","import {Server} from 'net-ipc';\nimport {BridgeInstanceConnection, BridgeInstanceConnectionStatus} from \"./BridgeInstanceConnection\";\nimport {GatewayIntentsString, Snowflake} from \"discord.js\";\nimport {ClusterCalculator} from \"./ClusterCalculator\";\nimport {BridgeClusterConnection, BridgeClusterConnectionStatus, HeartbeatResponse} from \"./BridgeClusterConnection\";\nimport {ShardingUtil} from \"../general/ShardingUtil\";\n\nexport class Bridge {\n    public readonly port: number;\n    public readonly server: Server;\n    public readonly connectedInstances: Map<string, BridgeInstanceConnection> = new Map();\n    private readonly token: string;\n    private readonly intents: GatewayIntentsString[];\n    private readonly shardsPerCluster: number = 1;\n    private readonly clusterToStart: number = 1\n    private readonly reclusteringTimeoutInMs: number;\n    private readonly ignoreHeartbeatMissed: boolean = false;\n\n    private readonly clusterCalculator: ClusterCalculator;\n\n    private readonly eventMap: BridgeEventListeners = {\n        CLUSTER_READY: undefined,\n        CLUSTER_HEARTBEAT_FAILED: undefined,\n        CLUSTER_STOPPED: undefined,\n        CLUSTER_SPAWNED: undefined,\n        CLUSTER_RECLUSTER: undefined,\n        INSTANCE_CONNECTED: undefined,\n        INSTANCE_DISCONNECTED: undefined,\n        INSTANCE_STOP_ACK: undefined,\n        INSTANCE_STOP: undefined,\n        ERROR: undefined\n    }\n\n    constructor(port: number, token: string, intents: GatewayIntentsString[], shardsPerCluster: number, clusterToStart: number, reclusteringTimeoutInMs: number, ignoreHeartbeatMissed?: boolean) {\n        this.port = port;\n        this.token = token;\n        this.intents = intents;\n        this.clusterToStart = clusterToStart;\n        this.shardsPerCluster = shardsPerCluster;\n        this.reclusteringTimeoutInMs = reclusteringTimeoutInMs;\n        this.ignoreHeartbeatMissed = ignoreHeartbeatMissed || false;\n\n        this.clusterCalculator = new ClusterCalculator(this.clusterToStart, this.shardsPerCluster);\n\n        this.server = new Server({\n            port: this.port,\n        })\n    }\n\n    public start(): void {\n        this.server.start().then(() => {\n            this.startListening();\n        })\n\n        this.interval();\n    }\n\n    private interval(): void {\n        setInterval(() => {\n            this.checkCreate();\n            this.checkRecluster();\n            this.heartbeat();\n        }, 5000)\n    }\n\n    private checkRecluster(): void {\n        // check if all clusters are used\n        const up = this.clusterCalculator.checkAllClustersConnected()\n        if (!up) {\n            return;\n        }\n\n        const connectedInstances: BridgeInstanceConnection[] = this.connectedInstances.values()\n            .filter(c => c.connectionStatus == BridgeInstanceConnectionStatus.READY)\n            .filter(c => !c.dev)\n            .filter(c => c.establishedAt + this.reclusteringTimeoutInMs < Date.now())\n            .toArray();\n\n        const {most, least} = this.clusterCalculator.findMostAndLeastClustersForConnections(connectedInstances);\n        if (most) {\n            const clusterToSteal = this.clusterCalculator.getClusterForConnection(most)[0] || undefined;\n            if (least && clusterToSteal) {\n                clusterToSteal.reclustering(least);\n\n                if (this.eventMap.CLUSTER_RECLUSTER) this.eventMap.CLUSTER_RECLUSTER(clusterToSteal, least, clusterToSteal.oldConnection!);\n                this.createCluster(least, clusterToSteal, true);\n\n                return;\n            }\n        }\n    }\n\n    private heartbeat(): void {\n        const clusters = this.clusterCalculator.clusterList;\n\n        clusters.forEach((cluster) => {\n            if (cluster.connection && cluster.connectionStatus == BridgeClusterConnectionStatus.CONNECTED && !cluster.heartbeatPending) {\n                cluster.heartbeatPending = true;\n                cluster.connection.eventManager.request<HeartbeatResponse>({\n                    type: 'CLUSTER_HEARTBEAT',\n                    data: {\n                        clusterID: cluster.clusterID\n                    }\n                }, 20000).then((r) => {\n                    cluster.removeMissedHeartbeat();\n                    cluster.heartbeatResponse = r;\n                }).catch((err) => {\n                    if (this.eventMap.CLUSTER_HEARTBEAT_FAILED) this.eventMap.CLUSTER_HEARTBEAT_FAILED(cluster, err)\n                    cluster.addMissedHeartbeat()\n\n                    if (cluster.missedHeartbeats > 7 && !cluster.connection?.dev && !this.ignoreHeartbeatMissed) {\n                        cluster.connection?.eventManager.send({\n                            type: 'CLUSTER_STOP',\n                            data: {\n                                id: cluster.clusterID\n                            }\n                        });\n                        cluster.connectionStatus = BridgeClusterConnectionStatus.DISCONNECTED;\n                        cluster.resetMissedHeartbeats()\n                    }\n                }).finally(() => {\n                    cluster.heartbeatPending = false;\n                })\n            }\n        });\n    }\n\n    private checkCreate(): void {\n        const optionalCluster = this.clusterCalculator.getNextCluster();\n\n        if (!optionalCluster) {\n            return;\n        }\n\n        const lowestLoadClient = this.clusterCalculator.getClusterWithLowestLoad(this.connectedInstances);\n        if (!lowestLoadClient) {\n            return;\n        }\n\n        this.createCluster(lowestLoadClient, optionalCluster)\n    }\n\n    private createCluster(connection: BridgeInstanceConnection, cluster: BridgeClusterConnection, recluster = false) {\n        cluster.resetMissedHeartbeats()\n        cluster.heartbeatResponse = undefined;\n        if (!recluster) {\n            cluster.setConnection(connection)\n        } else {\n            cluster.oldConnection?.eventManager.send({\n                type: 'CLUSTER_RECLUSTER',\n                data: {\n                    clusterID: cluster.clusterID\n                }\n            })\n        }\n        if (this.eventMap.CLUSTER_SPAWNED) this.eventMap.CLUSTER_SPAWNED(cluster, connection)\n        connection.eventManager.send({\n            type: 'CLUSTER_CREATE',\n            data: {\n                clusterID: cluster.clusterID,\n                instanceID: connection.instanceID,\n                totalShards: this.getTotalShards(),\n                shardList: cluster.shardList,\n                token: this.token,\n                intents: this.intents\n            }\n        });\n    }\n\n    public startListening(): void {\n        this.server.on('connect', (connection, payload) => {\n            const id = payload?.id;\n            const data = payload.data as unknown;\n            const dev = payload?.dev || false;\n            if (!id) {\n                connection.close('Invalid payload', false);\n                return;\n            }\n\n            if (this.connectedInstances.values().some(client => client.instanceID === id)) {\n                connection.close('Already connected', false);\n                return;\n            }\n\n            const bridgeInstanceConnection = new BridgeInstanceConnection(payload.id, connection, data, dev);\n            if (this.eventMap.INSTANCE_CONNECTED) this.eventMap.INSTANCE_CONNECTED(bridgeInstanceConnection);\n\n            bridgeInstanceConnection.onMessage((m: any) => {\n                if (m.type == 'CLUSTER_SPAWNED') {\n                    const cluster = this.clusterCalculator.getClusterForConnection(bridgeInstanceConnection).find(c => c.clusterID === m.data.id);\n                    if (cluster) {\n                        cluster.connectionStatus = BridgeClusterConnectionStatus.STARTING;\n                        cluster.spawnedAt = Date.now()\n                    }\n                    return;\n                }\n\n                if (m.type == 'CLUSTER_READY') {\n                    const cluster = this.clusterCalculator.getClusterForConnection(bridgeInstanceConnection).find(c => c.clusterID === m.data.id);\n                    if (cluster) {\n                        cluster.readyAt = Date.now();\n                        const readyDuration = cluster.readyAt - cluster.spawnedAt!;\n                        cluster.spawnedAt = undefined\n\n                        if (this.eventMap.CLUSTER_READY) this.eventMap.CLUSTER_READY(cluster, m.data.guilds || 0, m.data.members || 0, readyDuration );\n                        cluster.connectionStatus = BridgeClusterConnectionStatus.CONNECTED;\n                        if (cluster.oldConnection) {\n                            cluster.oldConnection.eventManager.send({\n                                type: 'CLUSTER_STOP',\n                                data: {\n                                    id: cluster.clusterID\n                                }\n                            });\n                            cluster.oldConnection = undefined;\n                        }\n                    }\n                    return;\n                }\n\n                if (m.type == 'CLUSTER_STOPPED') {\n                    const cluster = this.clusterCalculator.getClusterForConnection(bridgeInstanceConnection).find(c => c.clusterID === m.data.id);\n                    if (cluster) {\n                        cluster.readyAt = undefined;\n                        if (this.eventMap.CLUSTER_STOPPED) this.eventMap.CLUSTER_STOPPED(cluster);\n                        cluster.setConnection(undefined);\n                    }\n                    return;\n                }\n\n                if (m.type == \"INSTANCE_STOP\") {\n                    this.stopInstance(bridgeInstanceConnection);\n                }\n                return;\n            })\n\n            bridgeInstanceConnection.onRequest((m: any) => {\n                if (m.type == 'REDIRECT_REQUEST_TO_GUILD') {\n                    const guildID = m.guildID;\n                    const shardID = ShardingUtil.getShardIDForGuild(guildID, this.getTotalShards());\n                    const cluster = this.clusterCalculator.getClusterOfShard(shardID);\n                    if (!cluster) {\n                        return Promise.reject(new Error(\"cluster not found\"))\n                    }\n                    if (cluster.connectionStatus != BridgeClusterConnectionStatus.CONNECTED) {\n                        return Promise.reject(new Error(\"cluster not connected.\"))\n                    }\n\n                    if (!cluster.connection?.eventManager) {\n                        return Promise.reject(new Error(\"no connection defined.\"))\n                    }\n\n                    return cluster.connection.eventManager.request({\n                        type: 'REDIRECT_REQUEST_TO_GUILD',\n                        clusterID: cluster.clusterID,\n                        guildID: guildID,\n                        data: m.data\n                    }, 5000)\n                }\n\n                if (m.type == 'BROADCAST_EVAL') {\n                    const responses = Promise.all(\n                        this.connectedInstances.values().map(c => {\n                            return c.eventManager.request<unknown[]>({\n                                type: 'BROADCAST_EVAL',\n                                data: m.data,\n                            }, 5000);\n                        })\n                    )\n                    return new Promise<unknown[]>((resolve, reject) => {\n                        responses.then((r) => {\n                            resolve(r.flatMap(f => f))\n                        }).catch(reject);\n                    })\n                }\n\n                if (m.type == 'SELF_CHECK') {\n                    return {\n                        clusterList: [\n                            ...this.clusterCalculator.getClusterForConnection(bridgeInstanceConnection).map(c => c.clusterID),\n                            ...this.clusterCalculator.getOldClusterForConnection(bridgeInstanceConnection).map(c => c.clusterID)\n                        ]\n                    }\n                }\n\n                return Promise.reject(new Error(\"unknown type\"))\n            })\n\n            this.connectedInstances.set(connection.id, bridgeInstanceConnection)\n        });\n\n        this.server.on('disconnect', (connection, reason) => {\n            const closedConnection = this.connectedInstances.get(connection.id);\n            if (!closedConnection) {\n                return;\n            }\n\n            const clusters = this.clusterCalculator.getClusterForConnection(closedConnection);\n            for (const cluster of clusters) {\n                this.clusterCalculator.clearClusterConnection(cluster.clusterID);\n            }\n\n            if (this.eventMap.INSTANCE_DISCONNECTED) this.eventMap.INSTANCE_DISCONNECTED(closedConnection, reason);\n            this.connectedInstances.delete(connection.id);\n        });\n\n        this.server.on(\"message\", (message, connection) => {\n            this.sendMessageToInstance(connection.id, message);\n        })\n    }\n\n    sendMessageToInstance(instanceID: string, message: unknown): void {\n        if (!this.connectedInstances.has(instanceID)) {\n            return;\n        }\n\n        const instance = this.connectedInstances.get(instanceID);\n        if (instance) {\n            instance.messageReceive(message);\n        }\n    }\n\n    private getTotalShards() {\n        return this.shardsPerCluster * this.clusterToStart;\n    }\n\n\n    public on<K extends keyof BridgeEventListeners>(event: K, listener: BridgeEventListeners[K]): void {\n        this.eventMap[event] = listener;\n    }\n\n    public getClusters() {\n        return this.clusterCalculator.clusterList;\n    }\n\n    async stopAllInstances() {\n        const instances = Array.from(this.connectedInstances.values());\n        for (const instance of instances) {\n            instance.connectionStatus = BridgeInstanceConnectionStatus.PENDING_STOP;\n        }\n\n        for (const instance of instances) {\n            await this.stopInstance(instance, false);\n        }\n    }\n\n    async stopAllInstancesWithRestart() {\n        const instances = Array.from(this.connectedInstances.values());\n\n        for (const instance of instances) {\n            await this.stopInstance(instance);\n            await new Promise<void>((resolve) => {\n                setTimeout(async () => {\n                    resolve();\n                }, 1000 * 10);\n            })\n        }\n    }\n\n    async moveCluster(bridgeInstanceConnection: BridgeInstanceConnection, bridgeClusterConnection: BridgeClusterConnection) {\n        bridgeClusterConnection.reclustering(bridgeInstanceConnection);\n\n        this.createCluster(bridgeInstanceConnection, bridgeClusterConnection, true);\n    }\n\n    async stopInstance(bridgeInstanceConnection: BridgeInstanceConnection, recluster = true) {\n        bridgeInstanceConnection.connectionStatus = BridgeInstanceConnectionStatus.PENDING_STOP;\n\n        let clusterToStealConnection: BridgeClusterConnection | undefined;\n\n        await bridgeInstanceConnection.eventManager.send({\n            type: 'INSTANCE_STOP_ACK'\n        });\n        if (this.eventMap.INSTANCE_STOP_ACK) this.eventMap.INSTANCE_STOP_ACK(bridgeInstanceConnection);\n\n        if (recluster && this.connectedInstances.size > 1) {\n            while ((clusterToStealConnection = this.clusterCalculator.getClusterForConnection(bridgeInstanceConnection).filter(c =>\n                c.connectionStatus === BridgeClusterConnectionStatus.CONNECTED ||\n                c.connectionStatus == BridgeClusterConnectionStatus.STARTING ||\n                c.connectionStatus == BridgeClusterConnectionStatus.RECLUSTERING)[0]) !== undefined) {\n                // skip if the cluster is not connected\n                if (clusterToStealConnection.connectionStatus != BridgeClusterConnectionStatus.CONNECTED) break;\n\n                const least = this.clusterCalculator.getClusterWithLowestLoad(this.connectedInstances);\n                if (!least) {\n                    if (this.eventMap.ERROR) {\n                        this.eventMap.ERROR(\"Reclustering failed: No least cluster found.\");\n                    }\n                    await bridgeInstanceConnection.eventManager.send({\n                        type: 'CLUSTER_STOP',\n                        data: {\n                            id: clusterToStealConnection.clusterID\n                        }\n                    });\n                    clusterToStealConnection.connection = undefined;\n                    clusterToStealConnection.connectionStatus = BridgeClusterConnectionStatus.DISCONNECTED;\n                    continue;\n                }\n\n                clusterToStealConnection.reclustering(least);\n\n                if (this.eventMap.CLUSTER_RECLUSTER) {\n                    this.eventMap.CLUSTER_RECLUSTER(clusterToStealConnection, least, clusterToStealConnection.oldConnection!);\n                }\n\n                this.createCluster(least, clusterToStealConnection, true);\n            }\n\n            return new Promise<void>((resolve) => {\n                const interval = setInterval(async () => {\n                    const cluster = this.clusterCalculator.getOldClusterForConnection(bridgeInstanceConnection)[0] || undefined;\n                    if (!cluster) {\n                        clearInterval(interval);\n                        await bridgeInstanceConnection.eventManager.send({\n                            type: 'INSTANCE_STOP'\n                        });\n                        if (this.eventMap.INSTANCE_STOP) this.eventMap.INSTANCE_STOP(bridgeInstanceConnection);\n                        \n                        this.connectedInstances.delete(bridgeInstanceConnection.connection.id);\n                        await bridgeInstanceConnection.connection.close(\"Instance stopped.\", false);\n                        resolve();\n                        return;\n                    }\n                }, 1000);\n            })\n        } else {\n            this.clusterCalculator.getClusterForConnection(bridgeInstanceConnection).forEach(cluster => {\n                cluster.connection = undefined;\n                cluster.connectionStatus = BridgeClusterConnectionStatus.DISCONNECTED;\n                if (this.eventMap.CLUSTER_STOPPED) this.eventMap.CLUSTER_STOPPED(cluster);\n            });\n\n            await bridgeInstanceConnection.eventManager.send({\n                type: 'INSTANCE_STOP'\n            });\n\n            if (this.eventMap.INSTANCE_STOP) this.eventMap.INSTANCE_STOP(bridgeInstanceConnection);\n\n            this.connectedInstances.delete(bridgeInstanceConnection.connection.id);\n            await bridgeInstanceConnection.connection.close(\"Instance stopped.\", true);\n        }\n    }\n\n    sendRequestToGuild(cluster: BridgeClusterConnection, guildID: Snowflake, data: unknown, timeout = 5000): Promise<unknown> {\n        if (!cluster.connection) {\n            return Promise.reject(new Error(\"No connection defined for cluster \" + cluster.clusterID));\n        }\n\n        return cluster.connection.eventManager.request({\n            type: 'REDIRECT_REQUEST_TO_GUILD',\n            clusterID: cluster.clusterID,\n            guildID: guildID,\n            data: data\n        }, timeout);\n    }\n}\n\nexport type BridgeEventListeners = {\n    'CLUSTER_READY': ((cluster: BridgeClusterConnection, guilds: number, members: number, readyDuration: number) => void) | undefined,\n    'CLUSTER_STOPPED': ((cluster: BridgeClusterConnection) => void) | undefined,\n    'CLUSTER_SPAWNED': ((cluster: BridgeClusterConnection, connection: BridgeInstanceConnection) => void) | undefined,\n    'CLUSTER_RECLUSTER': ((cluster: BridgeClusterConnection, newConnection: BridgeInstanceConnection, oldConnection: BridgeInstanceConnection) => void) | undefined,\n    'CLUSTER_HEARTBEAT_FAILED': ((cluster: BridgeClusterConnection, error: unknown) => void) | undefined,\n    'INSTANCE_CONNECTED': ((client: BridgeInstanceConnection) => void) | undefined,\n    'INSTANCE_DISCONNECTED': ((client: BridgeInstanceConnection, reason: string) => void) | undefined,\n    'INSTANCE_STOP_ACK': ((cluster: BridgeInstanceConnection) => void) | undefined,\n    'INSTANCE_STOP': ((cluster: BridgeInstanceConnection) => void) | undefined,\n    'ERROR': ((error: string) => void) | undefined,\n};\n","import {Client, GatewayIntentsString, Status} from \"discord.js\";\nimport {EventManager} from \"../general/EventManager\";\nimport os from \"os\";\nexport class Cluster<T extends Client> {\n\n    public readonly instanceID: number;\n\n    public readonly clusterID: number;\n\n    public readonly shardList: number[] = [];\n\n    public readonly totalShards: number;\n\n    public readonly token: string;\n\n    public readonly intents: GatewayIntentsString[];\n\n    public eventManager: EventManager;\n\n    public client!: T;\n\n    public onSelfDestruct?: () => void | Promise<void>;\n\n    private _shuttingDown = false;\n\n    private readonly eventMap: {\n        'message': ((message: unknown) => void) | undefined,\n        'request': ((message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void) | undefined,\n        'CLUSTER_READY': (() => void) | undefined,\n    } = {\n        message: undefined, request: undefined, CLUSTER_READY: undefined,\n    }\n\n    constructor(instanceID: number, clusterID: number, shardList: number[], totalShards: number, token: string, intents: GatewayIntentsString[]) {\n        this.instanceID = instanceID;\n        this.clusterID = clusterID;\n        this.shardList = shardList;\n        this.totalShards = totalShards;\n        this.token = token;\n        this.intents = intents;\n        this.eventManager = new EventManager((message: unknown) => {\n            return new Promise((resolve, reject) => {\n                if (typeof process.send !== 'function') {\n                    reject(new Error(\"Process does not support sending messages\"));\n                    return;\n                }\n\n                process.send?.(message, undefined, undefined, (error) => {\n                    if (error) {\n                        reject(error);\n                    } else {\n                        resolve();\n                    }\n                });\n            });\n        }, (message: unknown) => {\n            this._onMessage(message);\n        }, (message: unknown) => {\n            return this._onRequest(message);\n        });\n        process.on(\"message\", (message) => {\n            this.eventManager.receive(message);\n        })\n\n        const gracefulExit = async () => {\n            if (this._shuttingDown) return;\n            this._shuttingDown = true;\n            if (this.onSelfDestruct) {\n                await Promise.resolve(this.onSelfDestruct());\n            }\n            if (this.client) {\n                try { this.client.destroy(); } catch {}\n            }\n            process.exit(0);\n        };\n        process.once('SIGTERM', gracefulExit);\n        process.once('SIGINT', gracefulExit);\n    }\n\n    static initial<T extends Client>(): Cluster<T> {\n        const args = process.env;\n\n        if (args.SHARD_LIST == undefined || args.INSTANCE_ID == undefined || args.TOTAL_SHARDS == undefined || args.TOKEN == undefined || args.INTENTS == undefined || args.CLUSTER_ID == undefined) {\n            throw new Error(\"Missing required environment variables\");\n        }\n\n        const shardList = args.SHARD_LIST.split(',').map(Number);\n\n        const totalShards = Number(args.TOTAL_SHARDS);\n\n        const instanceID = Number(args.INSTANCE_ID);\n        const clusterID = Number(args.CLUSTER_ID);\n\n        const token = args.TOKEN;\n\n        const intents = args.INTENTS.split(',').map(i => i.trim()) as GatewayIntentsString[];\n\n        return new Cluster<T>(instanceID, clusterID, shardList, totalShards, token, intents);\n    }\n\n    triggerReady(guilds: number, members: number) {\n        this.eventManager.send({\n            type: 'CLUSTER_READY',\n            id: this.clusterID,\n            guilds: guilds,\n            members: members,\n        });\n\n        if(this.eventMap?.CLUSTER_READY) {\n            this.eventMap?.CLUSTER_READY();\n        }\n    }\n\n    triggerError(e: any) {\n        this.eventManager.send({\n            type: 'CLUSTER_ERROR',\n            id: this.clusterID,\n        });\n    }\n\n    private async wait(ms: number) {\n        return new Promise(resolve => setTimeout(resolve, ms));\n    }\n\n    private _onMessage(message: unknown): void {\n        const m = message as { type: string, data: unknown };\n        if(m.type == 'CUSTOM' && this.eventMap.message) {\n            this.eventMap.message!(m.data);\n        }\n    }\n\n    private _onRequest(message: unknown): unknown {\n        const m = message as { type: string, data: unknown };\n        if(m.type == 'CUSTOM' && this.eventMap.request) {\n            return new Promise((resolve, reject) => {\n                this.eventMap.request!(m.data, resolve, reject);\n            });\n        } else if(m.type == 'CLUSTER_HEARTBEAT'){\n            const startTime = process.hrtime.bigint();\n            const startUsage = process.cpuUsage();\n\n            (async () => {\n                await this.wait(500);\n            })();\n\n            const endTime = process.hrtime.bigint();\n            const usageDiff = process.cpuUsage(startUsage);\n\n            const elapsedTimeUs = Number((endTime - startTime) / 1000n);\n            const totalCPUTime = usageDiff.user + usageDiff.system;\n\n            const cpuCount = os.cpus().length;\n            const cpuPercent = (totalCPUTime / (elapsedTimeUs * cpuCount)) * 100;\n\n            // Collect per-shard ping information in addition to the overall ws ping\n            let shardPings: { id: number, ping: number, status: Status, uptime?: unknown, guilds: number, members: number }[] = [];\n            try {\n                const shards = this.client.ws.shards;\n\n                if(shards) {\n                    shards.forEach((shard) => {\n                        shardPings.push({ id: shard.id, ping: shard.ping, status: shard.status,\n                            guilds: this.client.guilds.cache.filter(g => g.shardId === shard.id).size,\n                            members: this.client.guilds.cache.filter(g => g.shardId === shard.id).reduce((acc, g) => acc + g.memberCount, 0)\n                        });\n\n                        this.client.shard?.fetchClientValues('uptime', shard.id).then(values => {\n                            shardPings[shard.id][\"uptime\"] = values\n                        }).catch(e => {\n\n                        })\n                    })\n                }\n            } catch (_) {\n                // ignore and keep empty shardPings on failure\n            }\n\n            return {\n                cpu: { raw: process.cpuUsage(), cpuPercent: cpuPercent.toFixed(2) },\n                memory: { raw: process.memoryUsage(),\n                    memoryPercent: ((process.memoryUsage().heapUsed / process.memoryUsage().heapTotal) * 100).toFixed(2) + '%',\n                    usage: (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + 'MB'\n                },\n                ping: this.client.ws.ping,\n                shardPings: shardPings,\n            }\n        } else if(m.type == 'BROADCAST_EVAL'){\n            const broadcast = message as { type: 'BROADCAST_EVAL', data: string }\n\n            const fn = eval(`(${broadcast.data})`);\n\n            const result = fn(this.client);\n            if(result instanceof Promise){\n                return new Promise((resolve, reject) => {\n                    result.then(res => {\n                        resolve(res);\n                    }).catch(err => {\n                        reject(err);\n                    });\n                });\n            } else {\n                return result;\n            }\n        } else if(m.type == 'SELF_DESTRUCT') {\n            return new Promise<void>(async (resolve) => {\n                if (!this._shuttingDown) {\n                    this._shuttingDown = true;\n                    if (this.onSelfDestruct) {\n                        await Promise.resolve(this.onSelfDestruct());\n                    }\n                    if (this.client) {\n                        try { this.client.destroy(); } catch {}\n                    }\n                }\n                resolve();\n                process.exit(0);\n            });\n        }\n        return undefined;\n    }\n\n    public on<K extends keyof ClusterEventListeners>(event: K, listener: ClusterEventListeners[K]): void {\n        this.eventMap[event] = listener;\n    }\n\n    public sendMessage(data: unknown) {\n        this.eventManager.send({\n            type: 'CUSTOM',\n            data: data,\n        });\n    }\n\n    public sendRequest(data: unknown, timeout = 5000): Promise<unknown> {\n        return this.eventManager.request({\n            type: 'CUSTOM',\n            data: data,\n        }, timeout);\n    }\n\n    public broadcastEval<Result>(fn: (cluster: T) => Result, timeout = 20000): Promise<Result[]> {\n        return this.eventManager.request({\n            type: 'BROADCAST_EVAL',\n            data: fn.toString(),\n        }, timeout);\n    }\n\n\n    public sendMessageToClusterOfGuild(guildID: string, message: unknown): void {\n        if (this.eventManager) {\n            this.eventManager.send({\n                type: 'REDIRECT_MESSAGE_TO_GUILD',\n                guildID: guildID,\n                data: message\n            });\n        }\n    }\n\n    public sendRequestToClusterOfGuild(guildID: string, message: unknown, timeout = 5000): Promise<unknown> {\n        return new Promise((resolve, reject) => {\n            if (this.eventManager) {\n                this.eventManager.request({\n                    type: 'REDIRECT_REQUEST_TO_GUILD',\n                    guildID: guildID,\n                    data: message\n                }, timeout).then((response) => {\n                    resolve(response);\n                }).catch((error) => {\n                    reject(error);\n                });\n            } else {\n                reject(new Error(\"Event manager is not initialized\"));\n            }\n        });\n    }\n}\n\nexport type ClusterEventListeners = {\n    message: (message: unknown) => void;\n    request: (message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void;\n\n    CLUSTER_READY: () => void;\n};\n","import {ChildProcess} from \"child_process\";\nimport {EventManager} from \"../general/EventManager\";\n\nexport type ClusterProcessState = 'starting' | 'running' | 'stopped';\n\nexport class ClusterProcess {\n    public readonly child: ChildProcess;\n    public readonly eventManager: EventManager;\n    public readonly id: number;\n    public readonly shardList: number[];\n    public readonly totalShards: number;\n    public status: ClusterProcessState;\n    public readonly createdAt: number = Date.now();\n\n    private _onMessage?: (message: unknown) => void;\n    private _onRequest?: (message: unknown) => unknown;\n\n    constructor(id: number, child: ChildProcess, shardList: number[], totalShards: number) {\n        this.id = id;\n        this.child = child;\n        this.shardList = shardList;\n        this.totalShards = totalShards;\n        this.status = 'starting';\n        this.eventManager = new EventManager((message) => {\n            return new Promise<void>((resolve, reject) => {\n                this.child.send(message, (error) => {\n                    if (error) {\n                        reject(error);\n                    } else {\n                        resolve();\n                    }\n                });\n            })\n        }, (message) => {\n            if (this._onMessage) {\n                this._onMessage(message);\n            }\n        }, (message) => {\n            if (this._onRequest) {\n                return this._onRequest(message);\n            }\n            return undefined;\n        })\n\n        this.child.on('message', (message) => {\n            this.eventManager.receive(message);\n        });\n\n        // Ensure we do not retain pending requests if the child dies or errors\n        this.child.on('exit', () => {\n            this.eventManager.close('child process exited');\n        });\n        this.child.on('error', () => {\n            this.eventManager.close('child process error');\n        });\n    }\n\n    onMessage(callback: (message: unknown) => void) {\n        this._onMessage = callback;\n    }\n\n    onRequest(callback: (message: unknown) => unknown) {\n        this._onRequest = callback;\n    }\n\n    public sendMessage(data: unknown) {\n        this.eventManager.send({\n            type: 'CUSTOM',\n            data: data,\n        });\n    }\n\n    public sendRequest(data: unknown, timeout = 5000): Promise<unknown> {\n        return this.eventManager.request({\n            type: 'CUSTOM',\n            data: data,\n        }, timeout);\n    }\n}","import {fork} from 'child_process';\nimport {ClusterProcess} from \"../cluster/ClusterProcess\";\nimport {GatewayIntentsString} from \"discord.js\";\nimport {ShardingUtil} from \"../general/ShardingUtil\";\n\nexport abstract class BotInstance {\n\n    private readonly entryPoint: string;\n\n    private readonly execArgv: string[];\n\n    public readonly clusters: Map<number, ClusterProcess> = new Map();\n\n    protected _shuttingDown = false;\n\n    protected constructor(entryPoint: string, execArgv?: string[]) {\n        this.entryPoint = entryPoint;\n        this.execArgv = execArgv ?? [];\n    }\n\n    protected readonly eventMap: BotInstanceEventListeners = {\n        'message': undefined,\n        'request': undefined,\n\n        'PROCESS_KILLED': undefined,\n        'PROCESS_SELF_DESTRUCT_ERROR': undefined,\n        'PROCESS_SPAWNED': undefined,\n        'ERROR': undefined,\n        'PROCESS_ERROR': undefined,\n        'CLUSTER_READY': undefined,\n        'CLUSTER_ERROR': undefined,\n        'CLUSTER_RECLUSTER': undefined,\n        'BRIDGE_CONNECTION_ESTABLISHED': undefined,\n        'BRIDGE_CONNECTION_CLOSED': undefined,\n        'BRIDGE_CONNECTION_STATUS_CHANGE': undefined,\n        'INSTANCE_STOP_ACK': undefined,\n        'INSTANCE_STOP': undefined,\n        'SELF_CHECK_SUCCESS': undefined,\n        'SELF_CHECK_ERROR': undefined,\n        'SELF_CHECK_RECEIVED': undefined,\n    }\n\n    protected startProcess(instanceID: number, clusterID: number, shardList: number[], totalShards: number, token: string, intents: GatewayIntentsString[]): void {\n        try {\n            const childProcess = fork(this.entryPoint, {\n                env: {\n                    INSTANCE_ID: instanceID.toString(),\n                    CLUSTER_ID: clusterID.toString(),\n                    SHARD_LIST: shardList.join(','),\n                    TOTAL_SHARDS: totalShards.toString(),\n                    TOKEN: token,\n                    INTENTS: intents.join(','),\n                    FORCE_COLOR: 'true'\n                },\n                stdio: 'inherit',\n                execArgv: this.execArgv,\n                silent: false,\n                detached: true,\n            })\n\n            const clusterProcess = new ClusterProcess(clusterID, childProcess, shardList, totalShards);\n\n            childProcess.stdout?.on('data', (data) => {\n                process.stdout.write(data);\n            });\n\n            childProcess.stderr?.on('data', (data) => {\n                process.stderr.write(data);\n            });\n\n            childProcess.on(\"spawn\", () => {\n                if(this.eventMap.PROCESS_SPAWNED) this.eventMap.PROCESS_SPAWNED(clusterProcess);\n\n                this.setClusterSpawned(clusterProcess);\n\n                this.clusters.set(clusterID, clusterProcess);\n\n                clusterProcess.onMessage((message) => {\n                    this.onMessage(clusterProcess, message);\n                })\n\n                clusterProcess.onRequest((message) => {\n                    return this.onRequest(clusterProcess, message);\n                });\n            });\n\n            childProcess.on(\"error\", (err) => {\n                if(this.eventMap.PROCESS_ERROR) this.eventMap.PROCESS_ERROR(clusterProcess, err);\n            })\n\n            childProcess.on(\"exit\", (code: number | null, signal: string | null) => {\n                this.killProcess(clusterProcess, `Process exited: ${code} ${signal}`);\n            })\n        } catch (error) {\n            throw new Error(`Failed to start process for cluster ${clusterID}: ${error instanceof Error ? error.message : String(error)}`);\n        }\n    }\n\n    protected async killProcess(clusterProcess: ClusterProcess, reason: string): Promise<unknown> {\n        clusterProcess.status = 'stopped';\n\n        return clusterProcess.eventManager.request({\n            type: 'SELF_DESTRUCT',\n            reason: reason\n        }, 5000).catch(() => {\n            if(this.eventMap.PROCESS_SELF_DESTRUCT_ERROR) this.eventMap.PROCESS_SELF_DESTRUCT_ERROR(clusterProcess, reason, 'Cluster didnt respond to shot-call.');\n        }).finally(() => {\n            if (clusterProcess.child && clusterProcess.child.pid) {\n                if(clusterProcess.child.kill(\"SIGKILL\")) {\n                    if(this.eventMap.PROCESS_KILLED) this.eventMap.PROCESS_KILLED(clusterProcess, reason, true);\n                } else {\n                    if(this.eventMap.ERROR) this.eventMap.ERROR(`Failed to kill process for cluster ${clusterProcess.id}`);\n                    clusterProcess.child.kill(\"SIGKILL\");\n                }\n\n                try {\n                    process.kill(-clusterProcess.child.pid)\n                } catch {\n\n                }\n            } else {\n                if(this.eventMap.PROCESS_KILLED) this.eventMap.PROCESS_KILLED(clusterProcess, reason, false);\n            }\n            this.clusters.delete(clusterProcess.id);\n            this.setClusterStopped(clusterProcess, reason);\n        }).then(() => new Promise<void>((res) => {\n            if (!clusterProcess.child || clusterProcess.child.exitCode !== null) return res();\n            clusterProcess.child.once('exit', () => res());\n        }))\n    }\n\n    protected abstract setClusterStopped(clusterProcess: ClusterProcess, reason: string): void;\n\n    protected abstract setClusterReady(clusterProcess: ClusterProcess, guilds: number, members: number): void;\n\n    protected abstract setClusterSpawned(clusterProcess: ClusterProcess): void;\n\n    public abstract start(): void;\n\n    private onMessage(clusterProcess: ClusterProcess, message: any): void {\n        if(message.type === 'CLUSTER_READY') {\n            clusterProcess.status = 'running';\n            if(this.eventMap.CLUSTER_READY) this.eventMap.CLUSTER_READY(clusterProcess);\n            this.setClusterReady(clusterProcess, message.guilds || 0, message.members || 0);\n        }\n\n        if (message.type === 'CLUSTER_ERROR') {\n            clusterProcess.status = 'stopped';\n            if(this.eventMap.CLUSTER_ERROR) this.eventMap.CLUSTER_ERROR(clusterProcess, message.error);\n            this.killProcess(clusterProcess, 'Cluster error: ' + message.error);\n        }\n\n        if(message.type == 'CUSTOM' && this.eventMap.message) {\n            this.eventMap.message!(clusterProcess, message.data);\n        }\n    }\n\n    protected abstract onRequest(clusterProcess: ClusterProcess, message: any): Promise<unknown>;\n\n    public on<K extends keyof BotInstanceEventListeners>(event: K, listener: BotInstanceEventListeners[K]): void {\n        this.eventMap[event] = listener;\n    }\n\n    public sendRequestToClusterOfGuild(guildID: string, message: unknown, timeout = 5000): Promise<unknown> {\n        return new Promise((resolve, reject) => {\n            for (const client of this.clusters.values()) {\n                const shardID = ShardingUtil.getShardIDForGuild(guildID, client.totalShards);\n                if (client.shardList.includes(shardID)) {\n                    client.eventManager.request({\n                        type: 'CUSTOM',\n                        data: message\n                    }, timeout).then(resolve).catch(reject);\n                    return;\n                }\n            }\n            reject(new Error(`No cluster found for guild ${guildID}`));\n        });\n    }\n\n    public sendRequestToCluster(cluster: ClusterProcess, message: unknown, timeout = 5000): Promise<unknown> {\n        return new Promise((resolve, reject) => {\n            cluster.eventManager.request({\n                type: 'CUSTOM',\n                data: message\n            }, timeout).then(resolve).catch(reject);\n            return;\n        });\n    }\n}\n\nexport type BotInstanceEventListeners = {\n    'message': ((clusterProcess: ClusterProcess,message: unknown) => void) | undefined,\n    'request': ((clusterProcess: ClusterProcess, message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void) | undefined,\n\n    'PROCESS_KILLED': ((clusterProcess: ClusterProcess, reason: string, processKilled: boolean) => void) | undefined,\n    'PROCESS_SELF_DESTRUCT_ERROR': ((clusterProcess: ClusterProcess, reason: string, error: unknown) => void) | undefined,\n    'PROCESS_SPAWNED': ((clusterProcess: ClusterProcess) => void) | undefined,\n    'PROCESS_ERROR': ((clusterProcess: ClusterProcess, error: unknown) => void) | undefined,\n    'CLUSTER_READY': ((clusterProcess: ClusterProcess) => void) | undefined,\n    'CLUSTER_ERROR': ((clusterProcess: ClusterProcess, error: unknown) => void) | undefined,\n    'CLUSTER_RECLUSTER': ((clusterProcess: ClusterProcess) => void) | undefined,\n    'ERROR': ((error: string) => void) | undefined,\n\n    'BRIDGE_CONNECTION_ESTABLISHED': (() => void) | undefined,\n    'BRIDGE_CONNECTION_CLOSED': ((reason: string) => void) | undefined,\n    'BRIDGE_CONNECTION_STATUS_CHANGE': ((status: number) => void) | undefined,\n    'INSTANCE_STOP_ACK': (() => void) | undefined,\n    'INSTANCE_STOP': (() => void) | undefined,\n\n    'SELF_CHECK_SUCCESS': (() => void) | undefined,\n    'SELF_CHECK_ERROR': ((error: string) => void) | undefined,\n    'SELF_CHECK_RECEIVED': ((data: { clusterList: number[] }) => void) | undefined,\n};","import {BotInstance} from \"./BotInstance\";\nimport {ClusterProcess} from \"../cluster/ClusterProcess\";\nimport {Client} from \"net-ipc\";\nimport {EventManager} from \"../general/EventManager\";\nimport {GatewayIntentsString} from \"discord.js\";\nimport {ShardingUtil} from \"../general/ShardingUtil\";\n\nexport enum BridgeConnectionStatus {\n    CONNECTED,\n    DISCONNECTED,\n}\n\nexport class ManagedInstance extends BotInstance {\n\n    private readonly host: string;\n\n    private readonly port: number;\n\n    private readonly instanceID: number;\n\n    private eventManager!: EventManager;\n\n    private connectionStatus: BridgeConnectionStatus = BridgeConnectionStatus.DISCONNECTED;\n\n    private data: unknown;\n\n    private dev: boolean = false;\n\n    constructor(entryPoint: string, host: string, port: number, instanceID: number, data: unknown, execArgv?: string[], dev?: boolean) {\n        super(entryPoint, execArgv);\n\n        this.host = host;\n        this.port = port;\n        this.instanceID = instanceID;\n        this.data = data;\n        this.dev = dev || false;\n    }\n\n    public start() {\n        const instance = new Client({\n            host: this.host,\n            port: this.port,\n            reconnect: true,\n            retries: 100\n        });\n\n        this.eventManager = new EventManager((message) => {\n            if (instance.status == 3) {\n                return instance.send(message);\n            }\n            return Promise.reject(new Error('Client is not ready to send messages'));\n        }, (message) => {\n            const m = message as { type: string, data: unknown };\n            if (m.type == 'CLUSTER_CREATE') {\n                this.onClusterCreate(m.data)\n            } else if (m.type == 'CLUSTER_STOP') {\n                this.onClusterStop(m.data);\n            } else if (m.type == 'CLUSTER_RECLUSTER') {\n                this.onClusterRecluster(m.data);\n            } else if (m.type == 'INSTANCE_STOP_ACK') {\n                if (this.eventMap.INSTANCE_STOP_ACK) this.eventMap.INSTANCE_STOP_ACK();\n            } else if (m.type == 'INSTANCE_STOP') {\n                if (this.eventMap.INSTANCE_STOP) this.eventMap.INSTANCE_STOP();\n            }\n        }, (message) => {\n            return this.onBridgeRequest(message);\n        });\n\n        setInterval(() => {\n            if (this.connectionStatus == BridgeConnectionStatus.CONNECTED) {\n                this.selfCheck();\n            }\n        }, 2500); // 5 minutes\n\n        instance.connect({\n            id: this.instanceID,\n            dev: this.dev,\n            data: this.data,\n        }).then(_ => {\n            if (this.eventMap.BRIDGE_CONNECTION_ESTABLISHED) this.eventMap.BRIDGE_CONNECTION_ESTABLISHED();\n            this.connectionStatus = BridgeConnectionStatus.CONNECTED;\n\n            instance.on(\"message\", (message) => {\n                this.eventManager?.receive(message);\n            })\n            instance.on(\"close\", (reason) => {\n                if (this.eventMap.BRIDGE_CONNECTION_CLOSED) this.eventMap.BRIDGE_CONNECTION_CLOSED(reason);\n\n                // kill all\n                if (this.connectionStatus == BridgeConnectionStatus.CONNECTED) {\n                    this.clusters.forEach((client) => {\n                        this.killProcess(client, 'Bridge connection closed');\n                    });\n                }\n                this.connectionStatus = BridgeConnectionStatus.DISCONNECTED;\n            });\n\n            instance.on(\"status\", (status) => {\n                if (this.eventMap.BRIDGE_CONNECTION_STATUS_CHANGE) this.eventMap.BRIDGE_CONNECTION_STATUS_CHANGE(status);\n\n                if (status == 4) {\n                    if (this.connectionStatus == BridgeConnectionStatus.CONNECTED) {\n                        this.clusters.forEach((client) => {\n                            this.killProcess(client, 'Bridge connection closed');\n                        });\n                    }\n                    this.connectionStatus = BridgeConnectionStatus.DISCONNECTED;\n                } else if (status == 3) {\n                    this.connectionStatus = BridgeConnectionStatus.CONNECTED;\n                    if (this.eventMap.BRIDGE_CONNECTION_ESTABLISHED) this.eventMap.BRIDGE_CONNECTION_ESTABLISHED();\n                }\n            });\n        })\n    }\n\n    private selfCheck() {\n        this.eventManager.request({\n            type: 'SELF_CHECK'\n        }, 1000 * 60).then((r) => {\n            const response = r as { clusterList: number[] };\n\n            if (this.eventMap.SELF_CHECK_RECEIVED) {\n                this.eventMap.SELF_CHECK_RECEIVED(response);\n            }\n\n            const startingClusters = this.clusters.values().filter(c => c.status == 'starting').toArray();\n            startingClusters.forEach((c: ClusterProcess) => {\n                if (Date.now() - c.createdAt > 10 * 60 * 1000) {\n                    this.killProcess(c, 'Cluster took too long to start');\n                }\n            })\n\n            // check if there is an wrong cluster on this host\n            const wrongClusters = this.clusters.values().filter(c => !response.clusterList.includes(c.id)).toArray();\n            if (wrongClusters.length > 0) {\n                if (this.eventMap.SELF_CHECK_ERROR) {\n                    this.eventMap.SELF_CHECK_ERROR(`Self check found wrong clusters: ${wrongClusters.map(c => c.id).join(', ')}`);\n                }\n                wrongClusters.forEach(c => {\n                    this.killProcess(c, 'Self check found wrong cluster');\n                });\n            } else {\n                if (this.eventMap.SELF_CHECK_SUCCESS) {\n                    this.eventMap.SELF_CHECK_SUCCESS();\n                }\n            }\n        }).catch((err) => {\n            if (this.eventMap.SELF_CHECK_ERROR) {\n                this.eventMap.SELF_CHECK_ERROR(`Self check failed: ${err}`);\n            }\n        });\n    }\n\n    protected setClusterStopped(client: ClusterProcess, reason: string): void {\n        this.eventManager?.send({\n            type: 'CLUSTER_STOPPED',\n            data: {\n                id: client.id,\n                reason: reason\n            }\n        }).catch(() => {\n            return null\n        });\n    }\n\n    protected setClusterReady(client: ClusterProcess, guilds: number, members: number): void {\n        this.eventManager?.send({\n            type: 'CLUSTER_READY',\n            data: {\n                id: client.id,\n                guilds: guilds,\n                members: members\n            }\n        });\n    }\n\n    protected setClusterSpawned(client: ClusterProcess): void {\n        this.eventManager?.send({\n            type: 'CLUSTER_SPAWNED',\n            data: {\n                id: client.id\n            }\n        });\n    }\n\n    private onClusterCreate(message: unknown) {\n        const m = message as {\n            clusterID: number,\n            shardList: number[],\n            totalShards: number,\n            token: string,\n            intents: GatewayIntentsString[]\n        }\n\n        if (this.clusters.has(m.clusterID)) {\n            this.eventManager?.send({\n                type: 'CLUSTER_STOPPED',\n                data: {\n                    id: m.clusterID,\n                    reason: 'Cluster already exists'\n                }\n            }).catch(() => {\n                return null\n            });\n            return;\n        }\n\n        this.startProcess(this.instanceID, m.clusterID, m.shardList, m.totalShards, m.token, m.intents);\n    }\n\n    private onClusterStop(message: unknown) {\n        const m = message as { id: number };\n        const cluster = this.clusters.get(m.id)\n        if (cluster) {\n            this.killProcess(cluster, `Request to stop cluster ${m.id}`);\n        }\n    }\n\n    private onClusterRecluster(message: unknown) {\n        const m = message as { clusterID: number }\n        const cluster = this.clusters.get(m.clusterID);\n        if (this.eventMap.CLUSTER_RECLUSTER && cluster) {\n            this.eventMap.CLUSTER_RECLUSTER(cluster);\n        }\n    }\n\n    protected onRequest(client: ClusterProcess, message: any): Promise<unknown> {\n        if (message.type === 'REDIRECT_REQUEST_TO_GUILD') {\n            const guildID = message.guildID;\n            const data = message.data;\n\n            const shardID = ShardingUtil.getShardIDForGuild(guildID, client.totalShards);\n            if (client.shardList.includes(shardID)) {\n                return client.eventManager.request({\n                    type: 'CUSTOM',\n                    data: data\n                }, 5000)\n            } else {\n                return this.eventManager.request({\n                    type: 'REDIRECT_REQUEST_TO_GUILD',\n                    guildID: guildID,\n                    data: data\n                }, 5000)\n            }\n        }\n\n        if (message.type == 'BROADCAST_EVAL') {\n            return this.eventManager.request({\n                type: 'BROADCAST_EVAL',\n                data: message.data\n            }, 5000)\n        }\n\n        if (message.type == 'CUSTOM' && this.eventMap.request) {\n            return new Promise((resolve, reject) => {\n                this.eventMap.request!(client, message.data, resolve, reject);\n            });\n        }\n\n        return Promise.reject(new Error(`Unknown request type: ${message.type}`));\n    }\n\n    private onBridgeRequest(message: any): Promise<unknown> {\n        if (message.type === 'REDIRECT_REQUEST_TO_GUILD') {\n            const clusterID = message.clusterID;\n            const data = message.data;\n\n            const cluster = this.clusters.get(clusterID);\n            if (cluster) {\n                return cluster.eventManager.request({\n                    type: 'CUSTOM',\n                    data: data\n                }, 5000)\n            } else {\n                return Promise.reject(new Error(`Cluster is not here. Cluster ID: ${clusterID}`));\n            }\n        } else if (message.type == 'CLUSTER_HEARTBEAT') {\n            const clusterID = message.data.clusterID;\n            const cluster = this.clusters.get(clusterID);\n            if (cluster) {\n                return new Promise<unknown>((resolve, reject) => {\n                    cluster.eventManager.request({\n                        type: 'CLUSTER_HEARTBEAT'\n                    }, 15000).then((r) => {\n                        resolve(r);\n                    }).catch((err) => {\n                        reject(err);\n                    });\n                })\n            } else {\n                return Promise.reject(new Error(`Cluster is not here. Cluster ID: ${clusterID}`));\n            }\n        } else if (message.type == 'BROADCAST_EVAL') {\n            return Promise.all(this.clusters.values().filter(c => c.status == 'running').map(c => {\n                return c.eventManager.request({\n                    type: 'BROADCAST_EVAL',\n                    data: message.data,\n                }, 5000);\n            }));\n        }\n\n        return Promise.reject(new Error(`Unknown request type: ${message.type}`));\n    }\n\n    stopInstance(): void {\n        this.eventManager?.send({\n            type: 'INSTANCE_STOP'\n        });\n    }\n}","import {BotInstance} from \"./BotInstance\";\nimport {ClusterProcess} from \"../cluster/ClusterProcess\";\nimport {GatewayIntentsString} from \"discord.js\";\nimport {ShardingUtil} from \"../general/ShardingUtil\";\n\nexport class StandaloneInstance extends BotInstance {\n    private readonly totalClusters: number;\n    private readonly shardsPerCluster: number;\n\n    public readonly token: string;\n    public readonly intents: GatewayIntentsString[];\n\n    constructor(entryPoint: string, shardsPerCluster: number, totalClusters: number, token: string, intents: GatewayIntentsString[], execArgv?: string[]) {\n        super(entryPoint, execArgv);\n        this.shardsPerCluster = shardsPerCluster;\n        this.totalClusters = totalClusters;\n        this.token = token;\n        this.intents = intents;\n    }\n\n    get totalShards(): number {\n        return this.shardsPerCluster * this.totalClusters;\n    }\n\n    private calculateClusters(): Record<number, number[]> {\n        const clusters: Record<number, number[]> = {};\n        for (let i = 0; i < this.totalClusters; i++) {\n            clusters[i] = [];\n            for (let j = 0; j < this.shardsPerCluster; j++) {\n                clusters[i].push(i * this.shardsPerCluster + j);\n            }\n        }\n        return clusters;\n    }\n\n    public start(): void {\n        const clusters = this.calculateClusters();\n        for (const [id, shardList] of Object.entries(clusters)) {\n            this.startProcess(1, Number(id), shardList, this.totalShards, this.token, this.intents);\n        }\n    }\n\n    protected setClusterStopped(clusterProcess: ClusterProcess, reason: string): void {\n        this.clusters.delete(clusterProcess.id);\n        if (!this._shuttingDown) {\n            this.restartProcess(clusterProcess);\n        }\n    }\n\n    public async shutdown(): Promise<void> {\n        this._shuttingDown = true;\n        await Promise.all(Array.from(this.clusters.values()).map(c => this.killProcess(c, 'Graceful shutdown')));\n    }\n\n    protected setClusterReady(clusterProcess: ClusterProcess): void {\n        \n    }\n\n    protected setClusterSpawned(clusterProcess: ClusterProcess): void {\n\n    }\n\n    private restartProcess(clusterProcess: ClusterProcess): void {\n        this.startProcess(1, clusterProcess.id, clusterProcess.shardList, this.totalShards, this.token, this.intents);\n    }\n\n    protected onRequest(clusterProcess: ClusterProcess, message: any): Promise<unknown> {\n        if(message.type === 'REDIRECT_REQUEST_TO_GUILD'){\n            const guildID = message.guildID;\n            const data = message.data;\n\n            const shardID = ShardingUtil.getShardIDForGuild(guildID, clusterProcess.totalShards);\n            if(clusterProcess.shardList.includes(shardID)) {\n                return clusterProcess.eventManager.request({\n                    type: 'CUSTOM',\n                    data: data\n                }, 5000)\n            } else {\n                return Promise.reject(new Error(`Shard ID ${shardID} not found in cluster ${clusterProcess.id} for guild ${guildID}`));\n            }\n        }\n\n        if(message.type == 'BROADCAST_EVAL') {\n            return Promise.all(\n                this.clusters.values().map(c => {\n                    return c.eventManager.request({\n                        type: 'BROADCAST_EVAL',\n                        data: message.data,\n                    }, 5000);\n                })\n            );\n        }\n\n        if(message.type == 'CUSTOM' && this.eventMap.request) {\n            return new Promise((resolve, reject) => {\n                this.eventMap.request!(clusterProcess, message.data, resolve, reject);\n            });\n        }\n\n        return Promise.reject(new Error(`Unknown request type: ${message.type}`));\n    }\n\n}"],"mappings":"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"}