registerModules static method
Register and load modules atomically with dependency resolution
Implementation
static Future<void> registerModules(
List<ZenModule> modules, ZenScope scope) async {
if (modules.isEmpty) return;
// Store original state for rollback
final originalScopeState = _captureOriginalScopeState(scope);
final originalModules = Map<String, ZenModule>.from(_modules);
try {
// 1. Collect all dependencies
final allModules = _collectAllDependencies(modules);
// 2. Validate no circular dependencies (can throw StateError)
_validateDependencyGraph(allModules);
// 3. Calculate load order
final loadOrder = _calculateLoadOrder(allModules);
ZenLogger.logInfo(
'Loading ${loadOrder.length} modules: ${loadOrder.map((m) => m.name).join(' -> ')}');
// 4. Load modules in dependency order (this can fail)
for (final module in loadOrder) {
// Register dependencies (this can throw)
module.register(scope);
// Initialize (this can throw)
await module.onInit(scope);
// Only add to registry after successful registration and init
_modules[module.name] = module;
ZenLogger.logDebug('✅ Loaded: ${module.name}');
}
ZenLogger.logInfo(
'✅ Successfully loaded all ${loadOrder.length} modules');
} catch (error, stackTrace) {
// Rollback: restore original module registry
_modules.clear();
_modules.addAll(originalModules);
// Rollback: restore original scope state
_restoreOriginalScopeState(scope, originalScopeState);
// Log the failure
ZenLogger.logError('Module registration failed', error, stackTrace);
// Re-throw original error without wrapping to preserve type
rethrow;
}
}