/** * Data Service - Market data ingestion service */ // Framework imports import { Hono } from 'hono'; import { cors } from 'hono/cors'; // Library imports import { initializeServiceConfig } from '@stock-bot/config'; import { getLogger, setLoggerConfig, shutdownLoggers } from '@stock-bot/logger'; import { createAndConnectMongoDBClient, MongoDBClient } from '@stock-bot/mongodb-client'; import { createAndConnectPostgreSQLClient, PostgreSQLClient } from '@stock-bot/postgres-client'; import { getQueue, initializeQueueSystem, shutdownAllQueues } from '@stock-bot/queue'; import { Shutdown } from '@stock-bot/shutdown'; // Local imports import { exchangeRoutes, healthRoutes, queueRoutes } from './routes'; // Initialize configuration with automatic monorepo config inheritance const config = await initializeServiceConfig(); const serviceConfig = config.service; const databaseConfig = config.database; const queueConfig = config.queue; // Initialize logger with config const loggingConfig = config.logging; if (loggingConfig) { setLoggerConfig({ logLevel: loggingConfig.level, logConsole: true, logFile: false, environment: config.environment, }); } const app = new Hono(); // Add CORS middleware app.use( '*', cors({ origin: '*', allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'], allowHeaders: ['Content-Type', 'Authorization'], credentials: false, }) ); const logger = getLogger('data-service'); const PORT = serviceConfig.port; let server: ReturnType | null = null; let postgresClient: PostgreSQLClient | null = null; let mongoClient: MongoDBClient | null = null; // Queue system will be initialized globally // Initialize shutdown manager const shutdown = Shutdown.getInstance({ timeout: 15000 }); // Mount routes app.route('/health', healthRoutes); app.route('/api/exchanges', exchangeRoutes); app.route('/api/queue', queueRoutes); // Initialize services async function initializeServices() { logger.info('Initializing data service...'); try { // Initialize MongoDB client logger.info('Connecting to MongoDB...'); const mongoConfig = databaseConfig.mongodb; mongoClient = await createAndConnectMongoDBClient({ uri: mongoConfig.uri, database: mongoConfig.database, host: mongoConfig.host || 'localhost', port: mongoConfig.port || 27017, timeouts: { connectTimeout: 30000, socketTimeout: 30000, serverSelectionTimeout: 5000, }, }); logger.info('MongoDB connected'); // Initialize PostgreSQL client logger.info('Connecting to PostgreSQL...'); const pgConfig = databaseConfig.postgres; postgresClient = await createAndConnectPostgreSQLClient({ host: pgConfig.host, port: pgConfig.port, database: pgConfig.database, username: pgConfig.user, password: pgConfig.password, poolSettings: { min: 2, max: pgConfig.poolSize || 10, idleTimeoutMillis: pgConfig.idleTimeout || 30000, }, }); logger.info('PostgreSQL connected'); // Initialize queue system logger.info('Initializing queue system...'); await initializeQueueSystem({ redis: queueConfig.redis, defaultJobOptions: queueConfig.defaultJobOptions, workers: 5, concurrency: 20, }); logger.info('Queue system initialized'); logger.info('All services initialized successfully'); } catch (error) { logger.error('Failed to initialize services', { error }); throw error; } } // Start server async function startServer() { await initializeServices(); server = Bun.serve({ port: PORT, fetch: app.fetch, development: config.environment === 'development', }); logger.info(`Data Service started on port ${PORT}`); } // Register shutdown handlers shutdown.onShutdown(async () => { if (server) { logger.info('Stopping HTTP server...'); try { server.stop(); logger.info('HTTP server stopped'); } catch (error) { logger.error('Error stopping HTTP server', { error }); } } }); shutdown.onShutdown(async () => { logger.info('Shutting down queue system...'); try { await shutdownAllQueues(); logger.info('Queue system shut down'); } catch (error) { logger.error('Error shutting down queue system', { error }); } }); shutdown.onShutdown(async () => { logger.info('Disconnecting from databases...'); try { if (mongoClient) { await mongoClient.disconnect(); } if (postgresClient) { await postgresClient.disconnect(); } logger.info('Database connections closed'); } catch (error) { logger.error('Error closing database connections', { error }); } }); shutdown.onShutdown(async () => { try { await shutdownLoggers(); process.stdout.write('Data service loggers shut down\n'); } catch (error) { process.stderr.write(`Error shutting down loggers: ${error}\n`); } }); // Start the service startServer().catch(error => { logger.error('Failed to start data service', { error }); process.exit(1); }); logger.info('Data service startup initiated'); // Export queue functions for providers export { getQueue };