added new exchanges system
This commit is contained in:
parent
95eda4a842
commit
263e9513b7
98 changed files with 4643 additions and 1496 deletions
263
apps/data-sync-service/src/index.ts
Normal file
263
apps/data-sync-service/src/index.ts
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/**
|
||||
* Data Sync Service - Sync raw MongoDB data to PostgreSQL master records
|
||||
*/
|
||||
import { Hono } from 'hono';
|
||||
import { cors } from 'hono/cors';
|
||||
import { loadEnvVariables } from '@stock-bot/config';
|
||||
import { getLogger, shutdownLoggers } from '@stock-bot/logger';
|
||||
import { connectMongoDB, disconnectMongoDB } from '@stock-bot/mongodb-client';
|
||||
import { connectPostgreSQL, disconnectPostgreSQL } from '@stock-bot/postgres-client';
|
||||
import { Shutdown } from '@stock-bot/shutdown';
|
||||
import { enhancedSyncManager } from './services/enhanced-sync-manager';
|
||||
import { syncManager } from './services/sync-manager';
|
||||
|
||||
// Load environment variables
|
||||
loadEnvVariables();
|
||||
|
||||
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 = parseInt(process.env.DATA_SYNC_SERVICE_PORT || '3005');
|
||||
let server: ReturnType<typeof Bun.serve> | null = null;
|
||||
|
||||
// Initialize shutdown manager
|
||||
const shutdown = Shutdown.getInstance({ timeout: 15000 });
|
||||
|
||||
// Basic health check endpoint
|
||||
app.get('/health', c => {
|
||||
return c.json({
|
||||
status: 'healthy',
|
||||
service: 'data-sync-service',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
});
|
||||
|
||||
// Manual sync trigger endpoints
|
||||
app.post('/sync/symbols', async c => {
|
||||
try {
|
||||
const result = await syncManager.syncQMSymbols();
|
||||
return c.json({ success: true, result });
|
||||
} catch (error) {
|
||||
logger.error('Manual symbol sync failed', { error });
|
||||
return c.json(
|
||||
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
|
||||
500
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/sync/exchanges', async c => {
|
||||
try {
|
||||
const result = await syncManager.syncQMExchanges();
|
||||
return c.json({ success: true, result });
|
||||
} catch (error) {
|
||||
logger.error('Manual exchange sync failed', { error });
|
||||
return c.json(
|
||||
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
|
||||
500
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Get sync status
|
||||
app.get('/sync/status', async c => {
|
||||
try {
|
||||
const status = await syncManager.getSyncStatus();
|
||||
return c.json(status);
|
||||
} catch (error) {
|
||||
logger.error('Failed to get sync status', { error });
|
||||
return c.json({ error: error instanceof Error ? error.message : 'Unknown error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// Enhanced sync endpoints
|
||||
app.post('/sync/exchanges/all', async c => {
|
||||
try {
|
||||
const clearFirst = c.req.query('clear') === 'true';
|
||||
const result = await enhancedSyncManager.syncAllExchanges(clearFirst);
|
||||
return c.json({ success: true, result });
|
||||
} catch (error) {
|
||||
logger.error('Enhanced exchange sync failed', { error });
|
||||
return c.json(
|
||||
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
|
||||
500
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/sync/provider-mappings/qm', async c => {
|
||||
try {
|
||||
const result = await enhancedSyncManager.syncQMProviderMappings();
|
||||
return c.json({ success: true, result });
|
||||
} catch (error) {
|
||||
logger.error('QM provider mappings sync failed', { error });
|
||||
return c.json(
|
||||
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
|
||||
500
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/sync/symbols/:provider', async c => {
|
||||
try {
|
||||
const provider = c.req.param('provider');
|
||||
const clearFirst = c.req.query('clear') === 'true';
|
||||
const result = await enhancedSyncManager.syncSymbolsFromProvider(provider, clearFirst);
|
||||
return c.json({ success: true, result });
|
||||
} catch (error) {
|
||||
logger.error('Enhanced symbol sync failed', { error });
|
||||
return c.json(
|
||||
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
|
||||
500
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Clear data endpoint
|
||||
app.post('/sync/clear', async c => {
|
||||
try {
|
||||
const result = await enhancedSyncManager.clearPostgreSQLData();
|
||||
return c.json({ success: true, result });
|
||||
} catch (error) {
|
||||
logger.error('Clear PostgreSQL data failed', { error });
|
||||
return c.json(
|
||||
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
|
||||
500
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Enhanced status endpoints
|
||||
app.get('/sync/status/enhanced', async c => {
|
||||
try {
|
||||
const status = await enhancedSyncManager.getSyncStatus();
|
||||
return c.json(status);
|
||||
} catch (error) {
|
||||
logger.error('Failed to get enhanced sync status', { error });
|
||||
return c.json({ error: error instanceof Error ? error.message : 'Unknown error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/sync/stats/exchanges', async c => {
|
||||
try {
|
||||
const stats = await enhancedSyncManager.getExchangeStats();
|
||||
return c.json(stats);
|
||||
} catch (error) {
|
||||
logger.error('Failed to get exchange stats', { error });
|
||||
return c.json({ error: error instanceof Error ? error.message : 'Unknown error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/sync/stats/provider-mappings', async c => {
|
||||
try {
|
||||
const stats = await enhancedSyncManager.getProviderMappingStats();
|
||||
return c.json(stats);
|
||||
} catch (error) {
|
||||
logger.error('Failed to get provider mapping stats', { error });
|
||||
return c.json({ error: error instanceof Error ? error.message : 'Unknown error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize services
|
||||
async function initializeServices() {
|
||||
logger.info('Initializing data sync service...');
|
||||
|
||||
try {
|
||||
// Initialize MongoDB client
|
||||
logger.info('Connecting to MongoDB...');
|
||||
await connectMongoDB();
|
||||
logger.info('MongoDB connected');
|
||||
|
||||
// Initialize PostgreSQL client
|
||||
logger.info('Connecting to PostgreSQL...');
|
||||
await connectPostgreSQL();
|
||||
logger.info('PostgreSQL connected');
|
||||
|
||||
// Initialize sync managers
|
||||
logger.info('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: process.env.NODE_ENV === '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 {
|
||||
await disconnectMongoDB();
|
||||
await disconnectPostgreSQL();
|
||||
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.error('Failed to start data sync service', { error });
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
logger.info('Data sync service startup initiated');
|
||||
Loading…
Add table
Add a link
Reference in a new issue