Fix TTS module initialization and dependency issues. Update module IDs for consistency, improve circular dependency detection, and fix UI Controller event handling.
This commit is contained in:
@@ -6,20 +6,52 @@ export class ModuleRegistry {
|
||||
constructor() {
|
||||
this.modules = {};
|
||||
this.readyPromises = {};
|
||||
this.moduleDependencies = new Map(); // Track module dependencies
|
||||
this.visitedModules = new Set(); // For circular dependency detection
|
||||
this.recursionStack = new Set(); // For circular dependency detection
|
||||
this.untrackedDependencies = new Map(); // Track unregistered dependencies
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a module
|
||||
* @param {BaseModule} module - Module to register
|
||||
* @param {Array<string>} [dependencies] - Optional array of module dependencies
|
||||
*/
|
||||
register(module) {
|
||||
register(module, dependencies = null) {
|
||||
if (!module || !module.id) {
|
||||
console.error('Invalid module - must have an id property');
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the module
|
||||
this.modules[module.id] = module;
|
||||
|
||||
// Store dependencies if provided, otherwise use module.dependencies
|
||||
if (dependencies) {
|
||||
this.moduleDependencies.set(module.id, dependencies);
|
||||
|
||||
// Also set them on the module itself for backwards compatibility
|
||||
if (module.dependencies === undefined) {
|
||||
module.dependencies = [...dependencies];
|
||||
}
|
||||
} else if (module.dependencies) {
|
||||
// Use the module's own dependencies property
|
||||
this.moduleDependencies.set(module.id, [...module.dependencies]);
|
||||
} else {
|
||||
// No dependencies
|
||||
this.moduleDependencies.set(module.id, []);
|
||||
}
|
||||
|
||||
// Check for circular dependencies
|
||||
this.visitedModules.clear();
|
||||
this.recursionStack.clear();
|
||||
const circularDependency = this.detectCircularDependency(module.id);
|
||||
if (circularDependency) {
|
||||
const errorMsg = `Circular dependency detected: ${circularDependency.join(' -> ')} -> ${circularDependency[0]}`;
|
||||
console.error(errorMsg);
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
// Create a promise that will resolve when this module is ready
|
||||
this.readyPromises[module.id] = new Promise((resolve) => {
|
||||
// Set up a state change listener for this module
|
||||
@@ -39,6 +71,76 @@ export class ModuleRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect circular dependencies using DFS algorithm
|
||||
* @param {string} moduleId - Starting module ID
|
||||
* @param {Array<string>} [path=[]] - Current dependency path
|
||||
* @returns {Array<string>|null} - Array representing the circular dependency path, or null if none
|
||||
*/
|
||||
detectCircularDependency(moduleId, path = []) {
|
||||
// If we've already checked this module completely, no need to check again
|
||||
if (this.visitedModules.has(moduleId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we're already visiting this module in the current path, we found a cycle
|
||||
if (this.recursionStack.has(moduleId)) {
|
||||
// Return the path that forms the cycle
|
||||
const cycleStartIndex = path.indexOf(moduleId);
|
||||
if (cycleStartIndex >= 0) {
|
||||
return path.slice(cycleStartIndex);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// Add to recursion stack to mark as being visited
|
||||
this.recursionStack.add(moduleId);
|
||||
path.push(moduleId);
|
||||
|
||||
// Get dependencies for this module
|
||||
const dependencies = this.getDependencies(moduleId);
|
||||
|
||||
// Check each dependency
|
||||
for (const depId of dependencies) {
|
||||
// Even if the dependency isn't registered yet, we need to track it
|
||||
// for potential circular dependencies that will manifest later
|
||||
// Create a temporary placeholder in the path for unregistered dependencies
|
||||
const depPath = [...path];
|
||||
if (!this.modules[depId]) {
|
||||
// Log that we're tracking an unregistered dependency
|
||||
console.log(`Module Registry: Tracking potential circular dependency with unregistered module: ${depId}`);
|
||||
// Add to the dependency tracking for future checks
|
||||
this.trackDependency(moduleId, depId);
|
||||
continue;
|
||||
}
|
||||
|
||||
const result = this.detectCircularDependency(depId, depPath);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from recursion stack as we're done with this module
|
||||
this.recursionStack.delete(moduleId);
|
||||
|
||||
// Mark as fully visited
|
||||
this.visitedModules.add(moduleId);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track an unregistered dependency
|
||||
* @param {string} moduleId - Module ID
|
||||
* @param {string} depId - Unregistered dependency ID
|
||||
*/
|
||||
trackDependency(moduleId, depId) {
|
||||
if (!this.untrackedDependencies.has(moduleId)) {
|
||||
this.untrackedDependencies.set(moduleId, new Set());
|
||||
}
|
||||
this.untrackedDependencies.get(moduleId).add(depId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a module by id
|
||||
* @param {string} id - Module id
|
||||
@@ -56,6 +158,33 @@ export class ModuleRegistry {
|
||||
return this.modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dependencies for a module
|
||||
* @param {string} id - Module id
|
||||
* @returns {Array<string>} - Array of dependencies
|
||||
*/
|
||||
getDependencies(id) {
|
||||
return this.moduleDependencies.get(id) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the dependency graph has any circular dependencies
|
||||
* @returns {Array<string>|null} - Array representing the circular dependency path, or null if none
|
||||
*/
|
||||
checkForCircularDependencies() {
|
||||
this.visitedModules.clear();
|
||||
|
||||
for (const moduleId in this.modules) {
|
||||
this.recursionStack.clear();
|
||||
const result = this.detectCircularDependency(moduleId);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a module to be ready (in FINISHED state)
|
||||
* @param {string} id - Module id to wait for
|
||||
@@ -92,3 +221,6 @@ export class ModuleRegistry {
|
||||
|
||||
// Create and export a singleton instance
|
||||
export const moduleRegistry = new ModuleRegistry();
|
||||
|
||||
// Make registry accessible globally
|
||||
window.moduleRegistry = moduleRegistry;
|
||||
|
||||
Reference in New Issue
Block a user