huge refactor to remove depenencie hell and add typesafe container

This commit is contained in:
Boki 2025-06-24 09:37:51 -04:00
parent 28b9822d55
commit 843a7b9b9b
148 changed files with 3603 additions and 2378 deletions

View file

@ -5,8 +5,8 @@
import { Hono } from 'hono';
import type { IServiceContainer } from '@stock-bot/handlers';
import { createHealthRoutes } from './health.routes';
import { createExchangeRoutes } from './exchange.routes';
import { createHealthRoutes } from './health.routes';
import { createMonitoringRoutes } from './monitoring.routes';
import { createPipelineRoutes } from './pipeline.routes';
@ -26,4 +26,4 @@ export function createRoutes(container: IServiceContainer): Hono {
app.route('/api/pipeline', pipelineRoutes);
return app;
}
}

View file

@ -2,8 +2,8 @@
* Exchange management routes - Refactored
*/
import { Hono } from 'hono';
import type { IServiceContainer } from '@stock-bot/types';
import { getLogger } from '@stock-bot/logger';
import type { IServiceContainer } from '@stock-bot/handlers';
import { createExchangeService } from '../services/exchange.service';
import { createSuccessResponse, handleError } from '../utils/error-handler';
import {
@ -259,4 +259,4 @@ export function createExchangeRoutes(container: IServiceContainer) {
});
return exchangeRoutes;
}
}

View file

@ -2,8 +2,8 @@
* Health check routes factory
*/
import { Hono } from 'hono';
import { getLogger } from '@stock-bot/logger';
import type { IServiceContainer } from '@stock-bot/handlers';
import { getLogger } from '@stock-bot/logger';
const logger = getLogger('health-routes');
@ -70,7 +70,10 @@ export function createHealthRoutes(container: IServiceContainer) {
health.checks.postgresql = { status: 'healthy', message: 'Connected and responsive' };
logger.debug('PostgreSQL health check passed');
} else {
health.checks.postgresql = { status: 'unhealthy', message: 'PostgreSQL client not available' };
health.checks.postgresql = {
status: 'unhealthy',
message: 'PostgreSQL client not available',
};
logger.warn('PostgreSQL health check failed - client not available');
}
} catch (error) {
@ -108,4 +111,4 @@ export function createHealthRoutes(container: IServiceContainer) {
}
// Export legacy routes for backward compatibility during migration
export const healthRoutes = createHealthRoutes({} as IServiceContainer);
export const healthRoutes = createHealthRoutes({} as IServiceContainer);

View file

@ -13,167 +13,200 @@ export function createMonitoringRoutes(container: IServiceContainer) {
/**
* Get overall system health
*/
monitoring.get('/', async (c) => {
monitoring.get('/', async c => {
try {
const health = await monitoringService.getSystemHealth();
// Set appropriate status code based on health
const statusCode = health.status === 'healthy' ? 200 :
health.status === 'degraded' ? 503 : 500;
const statusCode =
health.status === 'healthy' ? 200 : health.status === 'degraded' ? 503 : 500;
return c.json(health, statusCode);
} catch (error) {
return c.json({
status: 'error',
message: 'Failed to retrieve system health',
error: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
status: 'error',
message: 'Failed to retrieve system health',
error: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get cache/Dragonfly statistics
*/
monitoring.get('/cache', async (c) => {
monitoring.get('/cache', async c => {
try {
const stats = await monitoringService.getCacheStats();
return c.json(stats);
} catch (error) {
return c.json({
error: 'Failed to retrieve cache statistics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve cache statistics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get queue statistics
*/
monitoring.get('/queues', async (c) => {
monitoring.get('/queues', async c => {
try {
const stats = await monitoringService.getQueueStats();
return c.json({ queues: stats });
} catch (error) {
return c.json({
error: 'Failed to retrieve queue statistics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve queue statistics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get specific queue statistics
*/
monitoring.get('/queues/:name', async (c) => {
monitoring.get('/queues/:name', async c => {
try {
const queueName = c.req.param('name');
const stats = await monitoringService.getQueueStats();
const queueStats = stats.find(q => q.name === queueName);
if (!queueStats) {
return c.json({
error: 'Queue not found',
message: `Queue '${queueName}' does not exist`,
}, 404);
return c.json(
{
error: 'Queue not found',
message: `Queue '${queueName}' does not exist`,
},
404
);
}
return c.json(queueStats);
} catch (error) {
return c.json({
error: 'Failed to retrieve queue statistics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve queue statistics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get database statistics
*/
monitoring.get('/databases', async (c) => {
monitoring.get('/databases', async c => {
try {
const stats = await monitoringService.getDatabaseStats();
return c.json({ databases: stats });
} catch (error) {
return c.json({
error: 'Failed to retrieve database statistics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve database statistics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get specific database statistics
*/
monitoring.get('/databases/:type', async (c) => {
monitoring.get('/databases/:type', async c => {
try {
const dbType = c.req.param('type') as 'postgres' | 'mongodb' | 'questdb';
const stats = await monitoringService.getDatabaseStats();
const dbStats = stats.find(db => db.type === dbType);
if (!dbStats) {
return c.json({
error: 'Database not found',
message: `Database type '${dbType}' not found or not enabled`,
}, 404);
return c.json(
{
error: 'Database not found',
message: `Database type '${dbType}' not found or not enabled`,
},
404
);
}
return c.json(dbStats);
} catch (error) {
return c.json({
error: 'Failed to retrieve database statistics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve database statistics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get service metrics
*/
monitoring.get('/metrics', async (c) => {
monitoring.get('/metrics', async c => {
try {
const metrics = await monitoringService.getServiceMetrics();
return c.json(metrics);
} catch (error) {
return c.json({
error: 'Failed to retrieve service metrics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve service metrics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get detailed cache info (Redis INFO command output)
*/
monitoring.get('/cache/info', async (c) => {
monitoring.get('/cache/info', async c => {
try {
if (!container.cache) {
return c.json({
error: 'Cache not available',
message: 'Cache service is not enabled',
}, 503);
return c.json(
{
error: 'Cache not available',
message: 'Cache service is not enabled',
},
503
);
}
const info = await container.cache.info();
const stats = await monitoringService.getCacheStats();
return c.json({
parsed: stats,
raw: info,
});
} catch (error) {
return c.json({
error: 'Failed to retrieve cache info',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve cache info',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Health check endpoint for monitoring
*/
monitoring.get('/ping', (c) => {
return c.json({
status: 'ok',
monitoring.get('/ping', c => {
return c.json({
status: 'ok',
timestamp: new Date().toISOString(),
service: 'monitoring',
});
@ -182,78 +215,90 @@ export function createMonitoringRoutes(container: IServiceContainer) {
/**
* Get service status for all microservices
*/
monitoring.get('/services', async (c) => {
monitoring.get('/services', async c => {
try {
const services = await monitoringService.getServiceStatus();
return c.json({ services });
} catch (error) {
return c.json({
error: 'Failed to retrieve service status',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve service status',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get proxy statistics
*/
monitoring.get('/proxies', async (c) => {
monitoring.get('/proxies', async c => {
try {
const stats = await monitoringService.getProxyStats();
return c.json(stats || { enabled: false });
} catch (error) {
return c.json({
error: 'Failed to retrieve proxy statistics',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve proxy statistics',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Get comprehensive system overview
*/
monitoring.get('/overview', async (c) => {
monitoring.get('/overview', async c => {
try {
const overview = await monitoringService.getSystemOverview();
return c.json(overview);
} catch (error) {
return c.json({
error: 'Failed to retrieve system overview',
message: error instanceof Error ? error.message : 'Unknown error',
}, 500);
return c.json(
{
error: 'Failed to retrieve system overview',
message: error instanceof Error ? error.message : 'Unknown error',
},
500
);
}
});
/**
* Test direct BullMQ queue access
*/
monitoring.get('/test/queue/:name', async (c) => {
monitoring.get('/test/queue/:name', async c => {
const queueName = c.req.param('name');
const { Queue } = await import('bullmq');
const connection = {
host: 'localhost',
port: 6379,
db: 0, // All queues in DB 0
db: 0, // All queues in DB 0
};
const queue = new Queue(queueName, { connection });
try {
const counts = await queue.getJobCounts();
await queue.close();
return c.json({
return c.json({
queueName,
counts
counts,
});
} catch (error: any) {
await queue.close();
return c.json({
queueName,
error: error.message
}, 500);
return c.json(
{
queueName,
error: error.message,
},
500
);
}
});
return monitoring;
}
}

View file

@ -132,4 +132,4 @@ export function createPipelineRoutes(container: IServiceContainer) {
});
return pipeline;
}
}