refactoring continuing
This commit is contained in:
parent
742e590382
commit
a0a3b26177
20 changed files with 394 additions and 798 deletions
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
import type { IServiceContainer } from '@stock-bot/handlers';
|
||||
import type { IDataIngestionServices } from '../service-interfaces';
|
||||
import { ProxyManager } from '@stock-bot/proxy';
|
||||
|
||||
/**
|
||||
* Adapter that converts IDataIngestionServices to IServiceContainer
|
||||
|
|
@ -23,9 +22,10 @@ export class DataIngestionServiceAdapter implements IServiceContainer {
|
|||
// HTTP client not in current data services - will be added when needed
|
||||
return null;
|
||||
}
|
||||
get proxy() {
|
||||
// Return singleton proxy manager instance
|
||||
return ProxyManager.getInstance();
|
||||
get proxy(): any {
|
||||
// Proxy manager should be injected via Awilix container
|
||||
// This adapter is for legacy compatibility
|
||||
throw new Error('ProxyManager must be provided through Awilix container');
|
||||
}
|
||||
|
||||
// Database clients
|
||||
|
|
|
|||
174
libs/core/di/src/awilix-container.ts
Normal file
174
libs/core/di/src/awilix-container.ts
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
* Awilix DI Container Setup
|
||||
* Creates a decoupled, reusable dependency injection container
|
||||
*/
|
||||
|
||||
import { createContainer, asFunction, asValue, InjectionMode, type AwilixContainer } from 'awilix';
|
||||
import { createCache, type CacheProvider } from '@stock-bot/cache';
|
||||
import { ProxyManager } from '@stock-bot/proxy';
|
||||
import { getLogger } from '@stock-bot/logger';
|
||||
import type { IServiceContainer } from '@stock-bot/handlers';
|
||||
|
||||
// Configuration types
|
||||
export interface AppConfig {
|
||||
redis: {
|
||||
host: string;
|
||||
port: number;
|
||||
password?: string;
|
||||
username?: string;
|
||||
db?: number;
|
||||
};
|
||||
mongodb: {
|
||||
uri: string;
|
||||
database: string;
|
||||
};
|
||||
postgres: {
|
||||
host: string;
|
||||
port: number;
|
||||
database: string;
|
||||
user: string;
|
||||
password: string;
|
||||
};
|
||||
questdb?: {
|
||||
host: string;
|
||||
port: number;
|
||||
};
|
||||
proxy?: {
|
||||
cachePrefix?: string;
|
||||
ttl?: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and configure the DI container
|
||||
*/
|
||||
export function createServiceContainer(config: AppConfig): AwilixContainer {
|
||||
const container = createContainer({
|
||||
injectionMode: InjectionMode.PROXY,
|
||||
});
|
||||
|
||||
// Register configuration values
|
||||
container.register({
|
||||
// Configuration
|
||||
config: asValue(config),
|
||||
redisConfig: asValue(config.redis),
|
||||
mongoConfig: asValue(config.mongodb),
|
||||
postgresConfig: asValue(config.postgres),
|
||||
questdbConfig: asValue(config.questdb || { host: 'localhost', port: 9009 }),
|
||||
|
||||
// Core services with dependency injection
|
||||
logger: asFunction(() => getLogger('app')).singleton(),
|
||||
|
||||
// Cache with injected config and logger
|
||||
cache: asFunction(({ redisConfig, logger }) =>
|
||||
createCache({
|
||||
redisConfig,
|
||||
logger,
|
||||
keyPrefix: 'cache:',
|
||||
ttl: 3600,
|
||||
enableMetrics: true,
|
||||
})
|
||||
).singleton(),
|
||||
|
||||
// Proxy manager with injected cache and logger
|
||||
proxyManager: asFunction(({ cache, config, logger }) => {
|
||||
const manager = new ProxyManager(
|
||||
cache,
|
||||
config.proxy || {},
|
||||
logger
|
||||
);
|
||||
// Note: initialization happens in initializeServices function
|
||||
return manager;
|
||||
}).singleton(),
|
||||
|
||||
// HTTP client can be added here when decoupled
|
||||
httpClient: asFunction(() => {
|
||||
// TODO: Import and create HTTP client when decoupled
|
||||
return null;
|
||||
}).singleton(),
|
||||
|
||||
// Database clients - placeholders for now
|
||||
mongoClient: asFunction(() => {
|
||||
// TODO: Create MongoDB client
|
||||
return null;
|
||||
}).singleton(),
|
||||
|
||||
postgresClient: asFunction(() => {
|
||||
// TODO: Create PostgreSQL client
|
||||
return null;
|
||||
}).singleton(),
|
||||
|
||||
questdbClient: asFunction(() => {
|
||||
// TODO: Create QuestDB client
|
||||
return null;
|
||||
}).singleton(),
|
||||
|
||||
// Queue manager - placeholder
|
||||
queueManager: asFunction(() => {
|
||||
// TODO: Create queue manager when decoupled
|
||||
return null;
|
||||
}).singleton(),
|
||||
|
||||
// Build the IServiceContainer for handlers
|
||||
serviceContainer: asFunction((cradle) => ({
|
||||
logger: cradle.logger,
|
||||
cache: cradle.cache,
|
||||
proxy: cradle.proxyManager,
|
||||
http: cradle.httpClient,
|
||||
mongodb: cradle.mongoClient,
|
||||
postgres: cradle.postgresClient,
|
||||
questdb: cradle.questdbClient,
|
||||
queue: cradle.queueManager,
|
||||
} as IServiceContainer)).singleton(),
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize async services after container creation
|
||||
*/
|
||||
export async function initializeServices(container: AwilixContainer): Promise<void> {
|
||||
const logger = container.resolve('logger');
|
||||
|
||||
try {
|
||||
// Wait for cache to be ready first
|
||||
const cache = container.resolve('cache');
|
||||
if (cache && typeof cache.waitForReady === 'function') {
|
||||
await cache.waitForReady(10000);
|
||||
logger.info('Cache is ready');
|
||||
}
|
||||
|
||||
// Initialize proxy manager
|
||||
const proxyManager = container.resolve('proxyManager');
|
||||
if (proxyManager && typeof proxyManager.initialize === 'function') {
|
||||
await proxyManager.initialize();
|
||||
logger.info('Proxy manager initialized');
|
||||
}
|
||||
|
||||
// Initialize other async services as needed
|
||||
// ...
|
||||
|
||||
logger.info('All services initialized successfully');
|
||||
} catch (error) {
|
||||
logger.error('Failed to initialize services', { error });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Type definitions for container resolution
|
||||
export interface ServiceCradle {
|
||||
config: AppConfig;
|
||||
logger: any;
|
||||
cache: CacheProvider;
|
||||
proxyManager: ProxyManager;
|
||||
httpClient: any;
|
||||
mongoClient: any;
|
||||
postgresClient: any;
|
||||
questdbClient: any;
|
||||
queueManager: any;
|
||||
serviceContainer: IServiceContainer;
|
||||
}
|
||||
|
||||
// Export typed container
|
||||
export type ServiceContainer = AwilixContainer<ServiceCradle>;
|
||||
|
|
@ -6,4 +6,13 @@ export * from './pool-size-calculator';
|
|||
export * from './types';
|
||||
export * from './service-interfaces';
|
||||
export * from './service-factory';
|
||||
export * from './adapters/service-adapter';
|
||||
export * from './adapters/service-adapter';
|
||||
|
||||
// Awilix container exports
|
||||
export {
|
||||
createServiceContainer,
|
||||
initializeServices,
|
||||
type AppConfig,
|
||||
type ServiceCradle,
|
||||
type ServiceContainer
|
||||
} from './awilix-container';
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
import { getLogger } from '@stock-bot/logger';
|
||||
import { ConnectionFactory } from './connection-factory';
|
||||
import { PoolSizeCalculator } from './pool-size-calculator';
|
||||
import { ProxyManager } from '@stock-bot/proxy';
|
||||
import type {
|
||||
IDataIngestionServices,
|
||||
IServiceFactory,
|
||||
|
|
@ -45,9 +44,7 @@ export class DataIngestionServiceFactory implements IServiceFactory {
|
|||
this.createQueueConnection(connectionFactory, config)
|
||||
]);
|
||||
|
||||
// Initialize proxy manager
|
||||
logger.info('Initializing proxy manager...');
|
||||
await ProxyManager.initialize();
|
||||
// Note: Proxy manager initialization moved to Awilix container
|
||||
|
||||
const services: IDataIngestionServices = {
|
||||
mongodb: mongoPool.client,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue