Skip to content

Node Events

The NodeManager emits events for node connectivity and lifecycle. Listen on manager.nodeManager.

| Event | Signature | Description | | :--- | :--- | :--- | | nodeCreate | (node) | A new node was added to the manager. | | nodeConnect | (node) | Node WebSocket connected. Forwarded to manager. | | nodeDisconnect | (node, reason) | Node WebSocket disconnected. reason.code, reason.reason. Forwarded to manager. | | nodeError | (node, error, payload?) | Node encountered a REST or WebSocket error. Forwarded to manager. | | nodeReady | (node, payload) | Node session ready. payload.resumed, payload.sessionId. Forwarded to manager. | | nodeRaw | (node, payload) | Every raw WebSocket payload received from the node. Forwarded to manager. |

manager.nodeManager.on('nodeCreate', (node) => {
console.log(`[NodeManager] Node created: ${node.id}`);
});
manager.nodeManager.on('nodeConnect', (node) => {
console.log(`[NodeManager] ${node.id} connected | Session: ${node.sessionId}`);
});
manager.nodeManager.on('nodeDisconnect', (node, reason) => {
console.warn(`[NodeManager] ${node.id} disconnected: ${reason.reason} (${reason.code})`);
});
manager.nodeManager.on('nodeReady', (node, payload) => {
console.log(`[NodeManager] ${node.id} ready — resumed: ${payload.resumed}, session: ${payload.sessionId}`);
});
manager.nodeManager.on('nodeError', (node, error) => {
console.error(`[NodeManager] ${node.id} error: ${error.message}`);
});
manager.nodeManager.on('nodeRaw', (node, payload) => {
// Fires for every WebSocket message — use with caution in high-concurrency environments
if (payload.op === 'stats') {
console.log(`[NodeManager] ${node.id} stats: ${payload.players} players`);
}
});
// Create a node
const node = manager.nodeManager.createNode({
id: 'extra',
host: 'node2.example.com',
port: 2333,
authorization: 'pw',
});
// Get a node by id or instance
const node = manager.nodeManager.getNode('extra');
// Delete a node (movePlayers=true migrates players to another node)
manager.nodeManager.deleteNode('extra', false);
manager.nodeManager.deleteNode('extra', true); // migrate players
// Least-used nodes (only returns connected nodes)
const nodes = manager.nodeManager.leastUsedNodes('weighted');
const nodes2 = manager.nodeManager.leastUsedNodes('players'); // default
// Bulk operations
await manager.nodeManager.disconnectAll(deleteAllNodes, destroyPlayers);
await manager.nodeManager.connectAll();
await manager.nodeManager.reconnectAll();
// Serialize
const json = manager.nodeManager.toJSON();
// { nodeCount: 2, nodes: ['main', 'extra'] }
const node = manager.nodeManager.getNode('main');
// Metric summary
const metrics = node.nodeMetricSummary();
// { cpuLoad, systemLoad, memoryUsage, players, playingPlayers, uptime, ping, frameDeficit }
// Health status
const health = node.getHealthStatus();
// { status: 'healthy' | 'degraded' | 'critical' | 'offline', performance, isOverloaded, needsRestart, penaltyScore, estimatedRemainingCapacity, recommendations, metrics }
// Custom thresholds
const health2 = node.getHealthStatus({
cpu: { excellent: 0.3, good: 0.5, fair: 0.7, poor: 0.85 },
memory: { excellent: 60, good: 75, fair: 85, poor: 95 },
ping: { excellent: 50, good: 100, fair: 200, poor: 300 },
});
// Weighted score (lower = healthier, Infinity if disconnected)
console.log(node.weightedScore);
// Connection state
console.log(node.connected); // boolean
console.log(node.connectionStatus); // 'CONNECTING' | 'OPEN' | 'CLOSING' | 'CLOSED'
console.log(node.isNodeReconnecting); // boolean
console.log(node.reconnectionAttemptCount); // number
console.log(node.heartBeatPing); // ms
console.log(node.handshakePing); // ms (set on open)
console.log(node.isAlive); // boolean
const status = await node.routePlannerApi.getStatus();
await node.routePlannerApi.unmarkFailedAddress('1.2.3.4');
await node.routePlannerApi.unmarkAllFailedAddresses();

Use the nodeRaw event with caution — it fires for every WebSocket message and can be extremely verbose in high-concurrency environments.