refactored di into more composable parts
This commit is contained in:
parent
177fe30586
commit
26ebc77fe6
22 changed files with 908 additions and 281 deletions
96
libs/core/di/src/utils/lifecycle.ts
Normal file
96
libs/core/di/src/utils/lifecycle.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import type { AwilixContainer } from 'awilix';
|
||||
import type { ServiceDefinitions } from '../container/types';
|
||||
|
||||
interface ServiceWithLifecycle {
|
||||
connect?: () => Promise<void>;
|
||||
disconnect?: () => Promise<void>;
|
||||
close?: () => Promise<void>;
|
||||
initialize?: () => Promise<void>;
|
||||
shutdown?: () => Promise<void>;
|
||||
}
|
||||
|
||||
export class ServiceLifecycleManager {
|
||||
private readonly services = [
|
||||
{ name: 'cache', key: 'cache' as const },
|
||||
{ name: 'mongoClient', key: 'mongoClient' as const },
|
||||
{ name: 'postgresClient', key: 'postgresClient' as const },
|
||||
{ name: 'questdbClient', key: 'questdbClient' as const },
|
||||
{ name: 'queueManager', key: 'queueManager' as const },
|
||||
];
|
||||
|
||||
async initializeServices(
|
||||
container: AwilixContainer<ServiceDefinitions>,
|
||||
timeout = 30000
|
||||
): Promise<void> {
|
||||
const initPromises: Promise<void>[] = [];
|
||||
|
||||
for (const { name, key } of this.services) {
|
||||
const service = container.cradle[key] as ServiceWithLifecycle | null;
|
||||
|
||||
if (service) {
|
||||
const initPromise = this.initializeService(name, service);
|
||||
initPromises.push(
|
||||
Promise.race([
|
||||
initPromise,
|
||||
this.createTimeoutPromise(timeout, `${name} initialization timed out after ${timeout}ms`),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(initPromises);
|
||||
console.log('✅ All services initialized successfully');
|
||||
}
|
||||
|
||||
async shutdownServices(container: AwilixContainer<ServiceDefinitions>): Promise<void> {
|
||||
const shutdownPromises: Promise<void>[] = [];
|
||||
|
||||
// Shutdown in reverse order
|
||||
for (const { name, key } of [...this.services].reverse()) {
|
||||
const service = container.cradle[key] as ServiceWithLifecycle | null;
|
||||
|
||||
if (service) {
|
||||
shutdownPromises.push(this.shutdownService(name, service));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.allSettled(shutdownPromises);
|
||||
console.log('✅ All services shut down');
|
||||
}
|
||||
|
||||
private async initializeService(name: string, service: ServiceWithLifecycle): Promise<void> {
|
||||
try {
|
||||
if (typeof service.connect === 'function') {
|
||||
await service.connect();
|
||||
console.log(`✅ ${name} connected`);
|
||||
} else if (typeof service.initialize === 'function') {
|
||||
await service.initialize();
|
||||
console.log(`✅ ${name} initialized`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to initialize ${name}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async shutdownService(name: string, service: ServiceWithLifecycle): Promise<void> {
|
||||
try {
|
||||
if (typeof service.disconnect === 'function') {
|
||||
await service.disconnect();
|
||||
} else if (typeof service.close === 'function') {
|
||||
await service.close();
|
||||
} else if (typeof service.shutdown === 'function') {
|
||||
await service.shutdown();
|
||||
}
|
||||
console.log(`✅ ${name} shut down`);
|
||||
} catch (error) {
|
||||
console.error(`❌ Error shutting down ${name}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
private createTimeoutPromise(timeout: number, message: string): Promise<never> {
|
||||
return new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error(message)), timeout);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue