UNPKG

axiodb

Version:

The Pure JavaScript Alternative to SQLite. Embedded NoSQL database for Node.js with MongoDB-style queries, zero native dependencies, built-in InMemoryCache, and web GUI. Perfect for desktop apps, CLI tools, and embedded systems. No compilation, no platfor

173 lines 5.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConnectionManager = void 0; const events_1 = require("events"); const protocol_1 = require("../config/protocol"); const keys_1 = require("../config/keys"); /** * Connection Manager - Manages all active TCP connections */ class ConnectionManager extends events_1.EventEmitter { constructor() { super(); this.connections = new Map(); this.connectionCounter = 0; // Increase max listeners since we handle 1000+ concurrent connections this.setMaxListeners(0); // 0 = unlimited } /** * Add new connection */ addConnection(socket) { if (this.connections.size >= keys_1.MAX_CONNECTIONS) { return null; // Reject connection - server overload } const connectionId = this.generateConnectionId(); const info = { socket, buffer: new protocol_1.MessageBuffer(), connectedAt: Date.now(), lastActivity: Date.now(), requestCount: 0, }; this.connections.set(connectionId, info); // Setup socket handlers this.setupSocketHandlers(connectionId, socket, info); this.emit('connection:added', connectionId, socket.remoteAddress); return connectionId; } /** * Remove connection */ removeConnection(connectionId) { const info = this.connections.get(connectionId); if (info) { if (!info.socket.destroyed) { info.socket.destroy(); } this.connections.delete(connectionId); this.emit('connection:removed', connectionId); } } /** * Send response to client */ sendResponse(connectionId, response) { const info = this.connections.get(connectionId); if (!info || info.socket.destroyed) { return false; } try { const buffer = protocol_1.MessageFramer.encode(response); info.socket.write(buffer); info.lastActivity = Date.now(); return true; } catch (error) { this.emit('error', error, connectionId); return false; } } /** * Get connection info */ getConnection(connectionId) { return this.connections.get(connectionId); } /** * Get total active connections */ get activeConnections() { return this.connections.size; } /** * Get all connection IDs */ getAllConnectionIds() { return Array.from(this.connections.keys()); } /** * Close all connections gracefully */ closeAll() { for (const [connectionId, info] of this.connections.entries()) { if (!info.socket.destroyed) { info.socket.end(); } this.connections.delete(connectionId); } this.emit('all:closed'); } /** * Setup socket event handlers */ setupSocketHandlers(connectionId, socket, info) { socket.on('data', (chunk) => { try { info.lastActivity = Date.now(); const messages = info.buffer.addChunk(chunk); for (const message of messages) { info.requestCount++; this.emit('message', connectionId, message, socket); } } catch (error) { this.emit('error', error, connectionId); // Send error response const errorResponse = { id: 'error', statusCode: keys_1.StatusCode.BAD_REQUEST, message: keys_1.ErrorMessage.INVALID_MESSAGE_FORMAT, error: error instanceof Error ? error.message : String(error), }; this.sendResponse(connectionId, errorResponse); // Clear buffer for recovery info.buffer.clear(); } }); socket.on('error', (error) => { this.emit('socket:error', error, connectionId); this.removeConnection(connectionId); }); socket.on('close', (hadError) => { this.emit('socket:closed', connectionId, hadError); this.removeConnection(connectionId); }); socket.on('end', () => { this.emit('socket:end', connectionId); this.removeConnection(connectionId); }); socket.on('timeout', () => { this.emit('socket:timeout', connectionId); this.removeConnection(connectionId); }); } /** * Generate unique connection ID */ generateConnectionId() { this.connectionCounter++; return `conn_${this.connectionCounter}_${Date.now()}`; } /** * Get connection statistics */ getStats() { let totalRequests = 0; let oldestConnection = Date.now(); for (const info of this.connections.values()) { totalRequests += info.requestCount; if (info.connectedAt < oldestConnection) { oldestConnection = info.connectedAt; } } return { activeConnections: this.connections.size, maxConnections: keys_1.MAX_CONNECTIONS, totalRequests, oldestConnectionAge: Date.now() - oldestConnection, }; } } exports.ConnectionManager = ConnectionManager; //# sourceMappingURL=ConnectionManager.js.map