Skip to content

Node Events

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

EventSignatureDescription
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.