refactored data-sync service

This commit is contained in:
Boki 2025-06-18 19:39:40 -04:00
parent 1bb6b62408
commit 68d977f9e0
6 changed files with 183 additions and 134 deletions

View file

@ -1,16 +1,23 @@
/**
* 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-new';
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';
// Local imports
import { enhancedSyncManager } from './services/enhanced-sync-manager';
import { syncManager } from './services/sync-manager';
import { setMongoDBClient, setPostgreSQLClient } from './clients';
import { healthRoutes, syncRoutes, enhancedSyncRoutes, statsRoutes } from './routes';
// Initialize configuration with automatic monorepo config inheritance
const config = await initializeServiceConfig();
@ -50,140 +57,11 @@ let mongoClient: MongoDBClient | 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);
}
});
// Mount routes
app.route('/health', healthRoutes);
app.route('/sync', syncRoutes);
app.route('/sync', enhancedSyncRoutes);
app.route('/sync/stats', statsRoutes);
// Initialize services
async function initializeServices() {

View file

@ -0,0 +1,62 @@
import { Hono } from 'hono';
import { getLogger } from '@stock-bot/logger';
import { enhancedSyncManager } from '../services/enhanced-sync-manager';
const logger = getLogger('enhanced-sync-routes');
const enhancedSync = new Hono();
// Enhanced sync endpoints
enhancedSync.post('/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
);
}
});
enhancedSync.post('/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
);
}
});
enhancedSync.post('/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
);
}
});
// Enhanced status endpoints
enhancedSync.get('/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);
}
});
export { enhancedSync as enhancedSyncRoutes };

View file

@ -0,0 +1,14 @@
import { Hono } from 'hono';
const health = new Hono();
// Basic health check endpoint
health.get('/', c => {
return c.json({
status: 'healthy',
service: 'data-sync-service',
timestamp: new Date().toISOString(),
});
});
export { health as healthRoutes };

View file

@ -0,0 +1,5 @@
// Export all route modules
export { healthRoutes } from './health.routes';
export { syncRoutes } from './sync.routes';
export { enhancedSyncRoutes } from './enhanced-sync.routes';
export { statsRoutes } from './stats.routes';

View file

@ -0,0 +1,29 @@
import { Hono } from 'hono';
import { getLogger } from '@stock-bot/logger';
import { enhancedSyncManager } from '../services/enhanced-sync-manager';
const logger = getLogger('stats-routes');
const stats = new Hono();
// Statistics endpoints
stats.get('/exchanges', async c => {
try {
const statsData = await enhancedSyncManager.getExchangeStats();
return c.json(statsData);
} catch (error) {
logger.error('Failed to get exchange stats', { error });
return c.json({ error: error instanceof Error ? error.message : 'Unknown error' }, 500);
}
});
stats.get('/provider-mappings', async c => {
try {
const statsData = await enhancedSyncManager.getProviderMappingStats();
return c.json(statsData);
} catch (error) {
logger.error('Failed to get provider mapping stats', { error });
return c.json({ error: error instanceof Error ? error.message : 'Unknown error' }, 500);
}
});
export { stats as statsRoutes };

View file

@ -0,0 +1,61 @@
import { Hono } from 'hono';
import { getLogger } from '@stock-bot/logger';
import { syncManager } from '../services/sync-manager';
import { enhancedSyncManager } from '../services/enhanced-sync-manager';
const logger = getLogger('sync-routes');
const sync = new Hono();
// Manual sync trigger endpoints
sync.post('/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
);
}
});
sync.post('/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
sync.get('/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);
}
});
// Clear data endpoint
sync.post('/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
);
}
});
export { sync as syncRoutes };