updated di

This commit is contained in:
Boki 2025-06-21 20:07:43 -04:00
parent 3227388d25
commit c5a114d544
9 changed files with 545 additions and 306 deletions

View file

@ -1,22 +1,31 @@
/**
* Data Ingestion Service with Improved Dependency Injection
* This is the new version using type-safe services and constructor injection
*/
// Framework imports
import { initializeServiceConfig } from '@stock-bot/config';
import { Hono } from 'hono';
import { cors } from 'hono/cors';
// Library imports
import { getLogger, setLoggerConfig, shutdownLoggers } from '@stock-bot/logger';
import type { QueueManager } from '@stock-bot/queue';
import { Shutdown } from '@stock-bot/shutdown';
import { ProxyManager } from '@stock-bot/utils';
import { ServiceContainer, ConnectionFactory } from '@stock-bot/di';
import {
createDataIngestionServices,
disposeDataIngestionServices,
type IDataIngestionServices
} from '@stock-bot/di';
import { handlerRegistry } from '@stock-bot/handlers';
// Local imports
import { setupServiceContainer } from './setup/database-setup';
import { createRoutes } from './routes/create-routes';
import { initializeQMProviderNew } from './handlers/qm/qm.handler';
const config = initializeServiceConfig();
console.log('Data Service Configuration:', JSON.stringify(config, null, 2));
const serviceConfig = config.service;
// Configuration will be passed to service container setup
if (config.log) {
setLoggerConfig({
@ -33,27 +42,23 @@ const logger = getLogger('data-ingestion');
const PORT = serviceConfig.port;
let server: ReturnType<typeof Bun.serve> | null = null;
let serviceContainer: ServiceContainer | null = null;
let connectionFactory: ConnectionFactory | null = null;
let queueManager: QueueManager | null = null;
let services: IDataIngestionServices | null = null;
let app: Hono | null = null;
// Initialize shutdown manager
const shutdown = Shutdown.getInstance({ timeout: 15000 });
// Initialize services
// Initialize services with new DI pattern
async function initializeServices() {
logger.info('Initializing data-ingestion service...');
logger.info('Initializing data-ingestion service with improved DI...');
try {
// Initialize service container with connection pools
logger.debug('Setting up service container with connection pools...');
const { container, factory } = await setupServiceContainer();
serviceContainer = container;
connectionFactory = factory;
logger.info('Service container initialized with connection pools');
// Create all services using the service factory
logger.debug('Creating services using service factory...');
services = await createDataIngestionServices(config);
logger.info('All services created successfully');
// Create app with routes that have access to the container
// Create app with routes that have access to services
app = new Hono();
// Add CORS middleware
@ -67,47 +72,27 @@ async function initializeServices() {
})
);
// Create and mount routes with container
const routes = createRoutes(serviceContainer);
// Create and mount routes with services
const routes = createRoutes(services);
app.route('/', routes);
// Get queue manager from service container
logger.debug('Getting queue manager from service container...');
queueManager = await serviceContainer.resolveAsync<QueueManager>('queue');
logger.info('Queue system resolved from container');
// Initialize proxy manager
logger.debug('Initializing proxy manager...');
await ProxyManager.initialize();
logger.info('Proxy manager initialized');
// Initialize handlers using the handler registry
logger.debug('Initializing data handlers...');
const { initializeWebShareProvider } = await import('./handlers/webshare/webshare.handler');
const { initializeIBProvider } = await import('./handlers/ib/ib.handler');
const { initializeProxyProvider } = await import('./handlers/proxy/proxy.handler');
const { initializeQMProvider } = await import('./handlers/qm/qm.handler');
// Initialize handlers with new DI pattern
logger.debug('Initializing data handlers with new DI pattern...');
// Pass service container to handlers
initializeWebShareProvider(serviceContainer);
initializeIBProvider(serviceContainer);
initializeProxyProvider(serviceContainer);
initializeQMProvider(serviceContainer);
// Initialize QM handler with new pattern
initializeQMProviderNew(services);
logger.info('Data handlers initialized with service container');
// TODO: Convert other handlers to new pattern
// initializeWebShareProviderNew(services);
// initializeIBProviderNew(services);
// initializeProxyProviderNew(services);
// Register handlers with queue system
logger.debug('Registering handlers with queue system...');
try {
await queueManager.registerHandlers(handlerRegistry.getAllHandlers());
logger.info('Handlers registered with queue system');
} catch (error) {
logger.error('Failed to register handlers with queue system', {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
throw error;
}
logger.info('Data handlers initialized with new DI pattern');
// Create scheduled jobs from registered handlers
logger.debug('Creating scheduled jobs from registered handlers...');
@ -116,7 +101,7 @@ async function initializeServices() {
let totalScheduledJobs = 0;
for (const [handlerName, config] of allHandlers) {
if (config.scheduledJobs && config.scheduledJobs.length > 0) {
const queue = queueManager.getQueue(handlerName);
const queue = services.queue.getQueue(handlerName);
for (const scheduledJob of config.scheduledJobs) {
// Include handler and operation info in job data
@ -154,9 +139,9 @@ async function initializeServices() {
}
logger.info('Scheduled jobs created', { totalJobs: totalScheduledJobs });
// Now that all singletons are initialized and jobs are scheduled, start the workers
// Start queue workers
logger.debug('Starting queue workers...');
queueManager.startAllWorkers();
services.queue.startAllWorkers();
logger.info('Queue workers started');
logger.info('All services initialized successfully');
@ -191,8 +176,8 @@ async function startServer() {
shutdown.onShutdownHigh(async () => {
logger.info('Shutting down queue system...');
try {
if (queueManager) {
await queueManager.shutdown();
if (services?.queue) {
await services.queue.shutdown();
}
logger.info('Queue system shut down');
} catch (error) {
@ -213,22 +198,18 @@ shutdown.onShutdownHigh(async () => {
}
}, 'HTTP Server');
// Priority 2: Service container and connections (medium priority)
// Priority 2: Services and connections (medium priority)
shutdown.onShutdownMedium(async () => {
logger.info('Disposing service container and connections...');
logger.info('Disposing services and connections...');
try {
if (connectionFactory) {
await connectionFactory.disposeAll();
logger.info('Connection factory disposed, all pools closed');
}
if (serviceContainer) {
await serviceContainer.dispose();
logger.info('Service container disposed');
if (services) {
await disposeDataIngestionServices(services);
logger.info('All services disposed successfully');
}
} catch (error) {
logger.error('Error disposing service container', { error });
logger.error('Error disposing services', { error });
}
}, 'Service Container');
}, 'Services');
// Priority 3: Logger shutdown (lowest priority - runs last)
shutdown.onShutdownLow(async () => {
@ -247,6 +228,4 @@ startServer().catch(error => {
process.exit(1);
});
logger.info('Data service startup initiated');
// ProxyManager class and singleton instance are available via @stock-bot/utils
logger.info('Data service startup initiated with improved DI pattern');