4.3 KiB
4.3 KiB
DI Container Configuration Simplification
Overview
We've simplified the dependency injection container setup across all backend services by creating a new createServiceContainerFromConfig function that directly accepts the AppConfig, eliminating repetitive configuration mapping code.
Before vs After
Before (30+ lines per service)
// In each service's index.ts
const awilixConfig = {
redis: {
host: config.database.dragonfly.host,
port: config.database.dragonfly.port,
db: config.database.dragonfly.db,
},
mongodb: {
uri: config.database.mongodb.uri,
database: config.database.mongodb.database,
},
postgres: {
host: config.database.postgres.host,
port: config.database.postgres.port,
database: config.database.postgres.database,
user: config.database.postgres.user,
password: config.database.postgres.password,
},
questdb: {
enabled: false,
host: config.database.questdb.host,
httpPort: config.database.questdb.httpPort,
pgPort: config.database.questdb.pgPort,
influxPort: config.database.questdb.ilpPort,
database: config.database.questdb.database,
},
};
container = createServiceContainer(awilixConfig);
After (2-3 lines per service)
// In each service's index.ts
container = createServiceContainerFromConfig(config, {
enableQuestDB: false, // Service-specific options
enableMongoDB: true,
enablePostgres: true,
// ... other options
});
Benefits
- Code Reduction: ~30 lines reduced to 2-3 lines per service
- Centralized Mapping: Configuration structure mapping is now in one place
- Service-Specific Control: Each service can enable/disable specific components
- Type Safety: Direct use of AppConfig ensures type safety
- Maintainability: Changes to config structure only need updates in one place
Service Configurations
Data Ingestion Service
container = createServiceContainerFromConfig(config, {
enableQuestDB: false, // Not needed yet
enableMongoDB: true, // Stores raw data
enablePostgres: true, // Stores metadata
enableCache: true, // For rate limiting
enableQueue: true, // Job processing
enableBrowser: true, // Web scraping
enableProxy: true, // Proxy rotation
});
Data Pipeline Service
container = createServiceContainerFromConfig(config, {
enableQuestDB: config.database.questdb?.enabled || false,
enableMongoDB: true, // Reads raw data
enablePostgres: true, // Writes processed data
enableCache: true, // Query caching
enableQueue: true, // Job processing
enableBrowser: false, // Not needed
enableProxy: false, // Not needed
});
Web API Service
container = createServiceContainerFromConfig(config, {
enableQuestDB: false, // Not needed
enableMongoDB: true, // Reads data
enablePostgres: true, // Reads data
enableCache: true, // API caching
enableQueue: false, // No job processing
enableBrowser: false, // Not needed
enableProxy: false, // Not needed
});
Implementation Details
The new function in @stock-bot/di/awilix-container.ts:
- Accepts the standard AppConfig from
@stock-bot/config - Maps the nested config structure to what Awilix expects
- Provides sensible defaults for all options
- Only creates services that are enabled for the specific service
Migration Guide
To migrate a service:
-
Change the import:
// Before import { createServiceContainer, ... } from '@stock-bot/di'; // After import { createServiceContainerFromConfig, ... } from '@stock-bot/di'; -
Replace the config mapping:
// Before const awilixConfig = { /* 30+ lines of mapping */ }; container = createServiceContainer(awilixConfig); // After container = createServiceContainerFromConfig(config, { // Service-specific options }); -
Choose which services to enable based on your service's needs
Result
- 3 services updated: data-ingestion, data-pipeline, web-api
- ~90 lines of code removed (30 lines × 3 services)
- Cleaner, more maintainable codebase
- Easier to add new services with minimal boilerplate