#!/usr/bin/env node
/**
* Integrated Real-time Server - gRPC + WebSocket Bridge + Data Service
*
* Este servidor integra:
* - gRPC server optimizado para datos en tiempo real
* - WebSocket bridge para compatibilidad con navegadores
* - Data service conectado a MongoDB/Redis para datos reales
* - Dashboard con datos reales en tiempo real (no mΓ‘s mock data)
*/
import { getOptimizedGrpcServer } from './grpc-server.js';
import { getWebSocketGrpcBridge } from './websocket-bridge.js';
import { getDataService } from './data-service.js';
class IntegratedRealTimeServer {
constructor() {
this.grpcServer = null;
this.websocketBridge = null;
this.dataService = null;
this.isRunning = false;
// Configuration
this.config = {
grpcPort: process.env.GRPC_PORT || 50051,
wsPort: process.env.WS_PORT || 8080,
environment: process.env.NODE_ENV || 'development'
};
}
/**
* Initialize and start all services
*/
async start() {
try {
console.log('π Starting Integrated Real-time Server...');
console.log(`π Environment: ${this.config.environment}`);
console.log(`π§ gRPC Port: ${this.config.grpcPort}`);
console.log(`π WebSocket Port: ${this.config.wsPort}`);
console.log('β'.repeat(60));
// 1. Initialize Data Service (MongoDB/Redis)
console.log('π Step 1: Initializing Data Service...');
this.dataService = getDataService();
const dataServiceReady = await this.dataService.initialize();
if (dataServiceReady) {
console.log('β
Data Service connected to MongoDB/Redis');
// Test data access
const testStats = await this.dataService.getLiveStats();
console.log(`π Test data loaded: ${testStats.active_sessions} active sessions, ${testStats.total_messages} messages`);
} else {
console.warn('β οΈ Data Service initialization failed, will use fallback data');
}
// 2. Start gRPC Server
console.log('π‘ Step 2: Starting gRPC Server...');
this.grpcServer = getOptimizedGrpcServer();
const grpcStarted = await this.grpcServer.start(this.config.grpcPort);
if (grpcStarted) {
console.log(`β
gRPC Server running on port ${this.config.grpcPort}`);
} else {
throw new Error('Failed to start gRPC server');
}
// 3. Start WebSocket Bridge
console.log('π Step 3: Starting WebSocket Bridge...');
this.websocketBridge = getWebSocketGrpcBridge();
const bridgeStarted = await this.websocketBridge.initialize();
if (bridgeStarted) {
console.log(`β
WebSocket Bridge running on port ${this.config.wsPort}`);
} else {
throw new Error('Failed to start WebSocket bridge');
}
this.isRunning = true;
// Setup graceful shutdown
this.setupGracefulShutdown();
console.log('β'.repeat(60));
console.log('π Integrated Real-time Server STARTED successfully!');
console.log('');
console.log('π Service Status:');
console.log(` π Data Service: ${dataServiceReady ? 'π’ CONNECTED' : 'π‘ FALLBACK'}`);
console.log(` π‘ gRPC Server: π’ RUNNING (port ${this.config.grpcPort})`);
console.log(` π WebSocket Bridge: π’ RUNNING (port ${this.config.wsPort})`);
console.log('');
console.log('π Connection URLs:');
console.log(` gRPC: localhost:${this.config.grpcPort}`);
console.log(` WebSocket: ws://localhost:${this.config.wsPort}/grpc-ws`);
console.log(` Dashboard: http://localhost:3005`);
console.log('');
console.log('π‘ Dashboard ahora usa DATOS REALES en tiempo real!');
console.log(' - Sesiones activas: REAL count (no mΓ‘s hardcoded "1")');
console.log(' - EstadΓsticas: Desde MongoDB en tiempo real');
console.log(' - Conversaciones: Datos reales sin mock');
console.log('β'.repeat(60));
return true;
} catch (error) {
console.error('β Failed to start Integrated Real-time Server:', error);
await this.stop();
return false;
}
}
/**
* Stop all services gracefully
*/
async stop() {
if (!this.isRunning) {
console.log('β οΈ Server is not running');
return;
}
console.log('π Shutting down Integrated Real-time Server...');
try {
// Stop WebSocket Bridge
if (this.websocketBridge) {
console.log('π Stopping WebSocket Bridge...');
await this.websocketBridge.shutdown();
console.log('β
WebSocket Bridge stopped');
}
// Stop gRPC Server
if (this.grpcServer) {
console.log('π‘ Stopping gRPC Server...');
await this.grpcServer.stop();
console.log('β
gRPC Server stopped');
}
// Close Data Service
if (this.dataService) {
console.log('π Closing Data Service...');
await this.dataService.close();
console.log('β
Data Service closed');
}
this.isRunning = false;
console.log('β
Integrated Real-time Server shut down successfully');
} catch (error) {
console.error('β Error during shutdown:', error);
}
}
/**
* Setup graceful shutdown handlers
*/
setupGracefulShutdown() {
const shutdown = async (signal) => {
console.log(`\nπ‘ Received ${signal}, initiating graceful shutdown...`);
await this.stop();
process.exit(0);
};
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('uncaughtException', (error) => {
console.error('β Uncaught Exception:', error);
this.stop().then(() => process.exit(1));
});
process.on('unhandledRejection', (reason, promise) => {
console.error('β Unhandled Rejection at:', promise, 'reason:', reason);
this.stop().then(() => process.exit(1));
});
}
/**
* Get server status and statistics
*/
async getStatus() {
const status = {
isRunning: this.isRunning,
services: {
dataService: this.dataService ? await this.dataService.healthCheck() : null,
grpcServer: this.grpcServer ? await this.grpcServer.healthCheck() : null,
websocketBridge: this.websocketBridge ? this.websocketBridge.getStats() : null
},
config: this.config,
timestamp: Date.now()
};
return status;
}
/**
* Print detailed status
*/
async printStatus() {
const status = await this.getStatus();
console.log('π Server Status Report');
console.log('β'.repeat(50));
console.log(`Running: ${status.isRunning ? 'π’ YES' : 'π΄ NO'}`);
console.log(`Environment: ${status.config.environment}`);
console.log(`Timestamp: ${new Date(status.timestamp).toISOString()}`);
console.log('');
if (status.services.dataService) {
console.log('π Data Service:');
console.log(` Status: ${status.services.dataService.status === 'healthy' ? 'π’' : 'π‘'} ${status.services.dataService.status}`);
console.log(` MongoDB: ${status.services.dataService.mongodb ? 'π’' : 'π΄'}`);
console.log(` Redis: ${status.services.dataService.redis ? 'π’' : 'π΄'}`);
}
if (status.services.grpcServer) {
console.log('π‘ gRPC Server:');
console.log(` Status: ${status.services.grpcServer.status === 'healthy' ? 'π’' : 'π΄'} ${status.services.grpcServer.status}`);
console.log(` Connections: ${status.services.grpcServer.connections}`);
console.log(` Streams: ${status.services.grpcServer.streams}`);
}
if (status.services.websocketBridge) {
console.log('π WebSocket Bridge:');
console.log(` Connected Clients: ${status.services.websocketBridge.connectedClients}`);
console.log(` Port: ${status.services.websocketBridge.port}`);
}
console.log('β'.repeat(50));
}
}
// CLI handling
if (process.argv[1].endsWith('integrated-server.js')) {
const server = new IntegratedRealTimeServer();
const command = process.argv[2];
switch (command) {
case 'start':
case undefined:
server.start().then((success) => {
if (!success) {
process.exit(1);
}
});
break;
case 'status':
server.printStatus().then(() => {
process.exit(0);
});
break;
case 'stop':
server.stop().then(() => {
process.exit(0);
});
break;
default:
console.log('Usage: node integrated-server.js [start|stop|status]');
console.log('');
console.log('Commands:');
console.log(' start - Start the integrated server (default)');
console.log(' status - Show server status');
console.log(' stop - Stop the server gracefully');
process.exit(1);
}
}
export default IntegratedRealTimeServer;