Files
makemd/server/src/core/runtime/DomainRegistry.ts

163 lines
4.4 KiB
TypeScript
Raw Normal View History

import { logger } from '../../utils/logger';
import { FeatureGovernanceService } from '../governance/FeatureGovernanceService';
import { SERVICE_CONFIGS, ServiceConfig } from '../../config/serviceConfig';
export interface DomainModule {
name: string;
priority: number;
init: () => Promise<void>;
isAgi?: boolean;
config?: ServiceConfig;
}
class ServiceStateManager {
private static instance: ServiceStateManager;
private enabledServices: Set<string>;
private initializedServices: Set<string> = new Set();
private failedServices: Map<string, string> = new Map();
private constructor() {
this.enabledServices = new Set(
SERVICE_CONFIGS.filter(s => s.enabled).map(s => s.name)
);
}
static getInstance(): ServiceStateManager {
if (!this.instance) {
this.instance = new ServiceStateManager();
}
return this.instance;
}
isEnabled(name: string): boolean {
return this.enabledServices.has(name);
}
enable(name: string): void {
this.enabledServices.add(name);
}
disable(name: string): void {
this.enabledServices.delete(name);
}
markInitialized(name: string): void {
this.initializedServices.add(name);
this.failedServices.delete(name);
}
markFailed(name: string, error: string): void {
this.failedServices.set(name, error);
}
getStatus(): {
enabled: string[];
initialized: string[];
failed: Map<string, string>;
} {
return {
enabled: Array.from(this.enabledServices),
initialized: Array.from(this.initializedServices),
failed: new Map(this.failedServices),
};
}
getAllServices(): Array<{
name: string;
enabled: boolean;
initialized: boolean;
error?: string;
config?: ServiceConfig;
}> {
return SERVICE_CONFIGS.map(config => ({
name: config.name,
enabled: this.enabledServices.has(config.name),
initialized: this.initializedServices.has(config.name),
error: this.failedServices.get(config.name),
config,
}));
}
setEnabledServices(services: string[]): void {
this.enabledServices = new Set(services);
}
}
export const serviceStateManager = ServiceStateManager.getInstance();
export class DomainRegistry {
private static modules: DomainModule[] = [];
static register(module: DomainModule) {
const config = SERVICE_CONFIGS.find(s => s.name === module.name);
this.modules.push({ ...module, config });
}
static async bootstrap(tenantId?: string) {
const sortedModules = [...this.modules].sort((a, b) => a.priority - b.priority);
const isAgiBaseMode = await FeatureGovernanceService.isEnabled('CORE_AGI_BASE_MODE', tenantId);
const state = ServiceStateManager.getInstance();
const enabledCount = sortedModules.filter(m => state.isEnabled(m.name)).length;
logger.info(`[DomainRegistry] Bootstrapping ${enabledCount}/${sortedModules.length} modules... (AGI Base Mode: ${isAgiBaseMode})`);
for (const module of sortedModules) {
if (!state.isEnabled(module.name)) {
logger.info(`[DomainRegistry] Skipping disabled module: ${module.name}`);
continue;
}
if (module.isAgi && isAgiBaseMode) {
logger.warn(`[DomainRegistry] Skipping Heavy AGI module: ${module.name} (Base Mode Active)`);
continue;
}
try {
await module.init();
state.markInitialized(module.name);
logger.info(`[DomainRegistry] Module initialized: ${module.name}`);
} catch (err: unknown) {
const errorMessage = err instanceof Error ? err.message : String(err);
logger.error(`[DomainRegistry] Module ${module.name} failed to initialize: ${errorMessage}`);
state.markFailed(module.name, errorMessage);
if (module.priority < 10) {
throw err;
}
}
}
logger.info('✅ [DomainRegistry] Bootstrap completed successfully.');
}
static Priority = {
CORE_INFRA: 0,
SECURITY: 5,
RUNTIME: 10,
BIZ_DOMAIN: 20,
AGI_HEAVY: 50,
SUPPORT: 100
};
static getDomains(): DomainModule[] {
return [...this.modules];
}
static getServiceStatus() {
return ServiceStateManager.getInstance().getAllServices();
}
static setEnabledServices(services: string[]): void {
ServiceStateManager.getInstance().setEnabledServices(services);
}
static enableService(name: string): void {
ServiceStateManager.getInstance().enable(name);
}
static disableService(name: string): void {
ServiceStateManager.getInstance().disable(name);
}
}