Refactor service registration and revert lazy loading implementation (#234)

This commit is contained in:
samanhappy
2025-07-20 22:30:09 +08:00
committed by GitHub
parent 0f00ad7200
commit e507bea2e3
4 changed files with 22 additions and 53 deletions

View File

@@ -17,14 +17,7 @@ const defaultConfig = {
mcpHubVersion: getPackageVersion(), mcpHubVersion: getPackageVersion(),
}; };
let dataService: DataService | null = null; const dataService: DataService = getDataService();
const getDataServiceInstance = (): DataService => {
if (!dataService) {
dataService = getDataService();
}
return dataService;
};
// Settings cache // Settings cache
let settingsCache: McpSettings | null = null; let settingsCache: McpSettings | null = null;
@@ -61,16 +54,13 @@ export const loadOriginalSettings = (): McpSettings => {
}; };
export const loadSettings = (): McpSettings => { export const loadSettings = (): McpSettings => {
return getDataServiceInstance().filterSettings!(loadOriginalSettings()); return dataService.filterSettings!(loadOriginalSettings());
}; };
export const saveSettings = (settings: McpSettings): boolean => { export const saveSettings = (settings: McpSettings): boolean => {
const settingsPath = getSettingsPath(); const settingsPath = getSettingsPath();
try { try {
const mergedSettings = getDataServiceInstance().mergeSettings!( const mergedSettings = dataService.mergeSettings!(loadOriginalSettings(), settings);
loadOriginalSettings(),
settings,
);
fs.writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2), 'utf8'); fs.writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2), 'utf8');
// Update cache after successful save // Update cache after successful save
@@ -88,7 +78,6 @@ export const saveSettings = (settings: McpSettings): boolean => {
*/ */
export const clearSettingsCache = (): void => { export const clearSettingsCache = (): void => {
settingsCache = null; settingsCache = null;
dataService = null; // Also clear the data service cache
}; };
/** /**

View File

@@ -13,7 +13,6 @@ import {
} from './services/sseService.js'; } from './services/sseService.js';
import { initializeDefaultUser } from './models/User.js'; import { initializeDefaultUser } from './models/User.js';
import { sseUserContextMiddleware } from './middlewares/userContext.js'; import { sseUserContextMiddleware } from './middlewares/userContext.js';
import { initializeServices } from './services/services.js';
// Get the current working directory (will be project root in most cases) // Get the current working directory (will be project root in most cases)
const currentFileDir = process.cwd() + '/src'; const currentFileDir = process.cwd() + '/src';
@@ -32,9 +31,6 @@ export class AppServer {
async initialize(): Promise<void> { async initialize(): Promise<void> {
try { try {
// Initialize services
await initializeServices();
// Initialize default admin user if no users exist // Initialize default admin user if no users exist
await initializeDefaultUser(); await initializeDefaultUser();

View File

@@ -1,3 +1,6 @@
import { createRequire } from 'module';
import { join } from 'path';
type Class<T> = new (...args: any[]) => T; type Class<T> = new (...args: any[]) => T;
interface Service<T> { interface Service<T> {
@@ -8,17 +11,19 @@ interface Service<T> {
const registry = new Map<string, Service<any>>(); const registry = new Map<string, Service<any>>();
const instances = new Map<string, unknown>(); const instances = new Map<string, unknown>();
export async function registerService<T>(key: string, entry: Service<T>) { export function registerService<T>(key: string, entry: Service<T>) {
// Try to load override immediately during registration // Try to load override immediately during registration
const overridePath = './' + key + 'x.js'; const overridePath = join(process.cwd(), 'src', 'services', key + 'x.ts');
await import(overridePath) try {
.then((mod) => { const require = createRequire(process.cwd());
const mod = require(overridePath);
const override = mod[key.charAt(0).toUpperCase() + key.slice(1) + 'x']; const override = mod[key.charAt(0).toUpperCase() + key.slice(1) + 'x'];
if (typeof override === 'function') { if (typeof override === 'function') {
entry.override = override; entry.override = override;
} }
}) } catch (error) {
.catch(() => {}); // Silently ignore if override doesn't exist // Silently ignore if override doesn't exist
}
registry.set(key, entry); registry.set(key, entry);
} }

View File

@@ -1,31 +1,10 @@
import { registerService, getService } from './registry.js'; import { registerService, getService } from './registry.js';
import { DataService, DataServiceImpl } from './dataService.js'; import { DataService, DataServiceImpl } from './dataService.js';
let initialized = false; registerService('dataService', {
let tempDataService: DataService | null = null;
async function initializeServices() {
if (initialized) return;
await registerService('dataService', {
defaultImpl: DataServiceImpl, defaultImpl: DataServiceImpl,
}); });
initialized = true;
tempDataService = null; // Clear temp service once real one is ready
}
export function getDataService(): DataService { export function getDataService(): DataService {
if (initialized) {
return getService<DataService>('dataService'); return getService<DataService>('dataService');
} }
// Return temporary service for cases where services haven't been initialized yet
// This allows module loading to work even before server initialization
if (!tempDataService) {
tempDataService = new DataServiceImpl();
}
return tempDataService;
}
export { initializeServices };