184 lines
5.2 KiB
TypeScript
184 lines
5.2 KiB
TypeScript
/**
|
|
* Data Sync Service - Sync raw MongoDB data to PostgreSQL master records
|
|
*/
|
|
|
|
// 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 { Shutdown } from '@stock-bot/shutdown';
|
|
import { enhancedSyncManager } from './services/enhanced-sync-manager';
|
|
import { syncManager } from './services/sync-manager';
|
|
// Local imports
|
|
import { setMongoDBClient, setPostgreSQLClient } from './clients';
|
|
import { enhancedSyncRoutes, healthRoutes, statsRoutes, syncRoutes } from './routes';
|
|
|
|
// Initialize configuration with automatic monorepo config inheritance
|
|
const config = await initializeServiceConfig();
|
|
const serviceConfig = config.service;
|
|
const databaseConfig = config.database;
|
|
|
|
// 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'],
|
|
allowHeaders: ['Content-Type', 'Authorization'],
|
|
credentials: false,
|
|
})
|
|
);
|
|
|
|
const logger = getLogger('data-sync-service');
|
|
const PORT = serviceConfig.port;
|
|
let server: ReturnType<typeof Bun.serve> | null = null;
|
|
let postgresClient: PostgreSQLClient | null = null;
|
|
let mongoClient: MongoDBClient | null = null;
|
|
|
|
// Initialize shutdown manager
|
|
const shutdown = Shutdown.getInstance({ timeout: 15000 });
|
|
|
|
// Mount routes
|
|
app.route('/health', healthRoutes);
|
|
app.route('/sync', syncRoutes);
|
|
app.route('/sync', enhancedSyncRoutes);
|
|
app.route('/sync/stats', statsRoutes);
|
|
|
|
// Initialize services
|
|
async function initializeServices() {
|
|
logger.info('Initializing data sync service...');
|
|
|
|
try {
|
|
// Initialize MongoDB client
|
|
logger.debug('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,
|
|
},
|
|
});
|
|
setMongoDBClient(mongoClient);
|
|
logger.info('MongoDB connected');
|
|
|
|
// Initialize PostgreSQL client
|
|
logger.debug('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,
|
|
},
|
|
});
|
|
setPostgreSQLClient(postgresClient);
|
|
logger.info('PostgreSQL connected');
|
|
|
|
// Initialize sync managers
|
|
logger.debug('Initializing sync managers...');
|
|
await syncManager.initialize();
|
|
await enhancedSyncManager.initialize();
|
|
logger.info('Sync managers 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 Sync 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 sync managers...');
|
|
try {
|
|
await syncManager.shutdown();
|
|
await enhancedSyncManager.shutdown();
|
|
logger.info('Sync managers shut down');
|
|
} catch (error) {
|
|
logger.error('Error shutting down sync managers', { 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 sync service loggers shut down\n');
|
|
} catch (error) {
|
|
process.stderr.write(`Error shutting down loggers: ${error}\n`);
|
|
}
|
|
});
|
|
|
|
// Start the service
|
|
startServer().catch(error => {
|
|
logger.fatal('Failed to start data sync service', { error });
|
|
process.exit(1);
|
|
});
|
|
|
|
logger.info('Data sync service startup initiated');
|