feat(di): improve initializer error handling with FailedInitializerRegistry
- Add FailedInitializerRegistry to track failed initializers - Add FailedInitializer value object to store failure context - Enhance exception messages with failed initializer context - Improve ClassNotInstantiable and ClassResolutionException with detailed context - Update InitializerProcessor to register failed initializers
This commit is contained in:
@@ -10,9 +10,11 @@ use App\Framework\Core\ValueObjects\ClassName;
|
||||
use App\Framework\Core\ValueObjects\MethodName;
|
||||
use App\Framework\DI\Container;
|
||||
use App\Framework\DI\Exceptions\InitializerCycleException;
|
||||
use App\Framework\DI\FailedInitializerRegistry;
|
||||
use App\Framework\DI\Initializer;
|
||||
use App\Framework\DI\InitializerDependencyGraph;
|
||||
use App\Framework\DI\ValueObjects\DependencyGraphNode;
|
||||
use App\Framework\DI\ValueObjects\FailedInitializer;
|
||||
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
||||
use App\Framework\Logging\Logger;
|
||||
use App\Framework\Logging\ValueObjects\LogContext;
|
||||
@@ -46,6 +48,8 @@ final readonly class InitializerProcessor
|
||||
$logger->debug("InitializerProcessor: Processing " . count($initializerResults) . " initializers");
|
||||
|
||||
$dependencyGraph = new InitializerDependencyGraph($this->reflectionProvider);
|
||||
/** @var FailedInitializer[] */
|
||||
$failedInitializers = [];
|
||||
|
||||
// Phase 1: Setup-Initializer sofort ausführen & Service-Initializer zum Graph hinzufügen
|
||||
foreach ($initializerResults as $discoveredAttribute) {
|
||||
@@ -94,18 +98,35 @@ final readonly class InitializerProcessor
|
||||
])
|
||||
);
|
||||
|
||||
// Track fehlgeschlagene Initializer für spätere Diagnose
|
||||
if ($returnType !== null && $returnType !== 'void') {
|
||||
$failedInitializers[] = new FailedInitializer(
|
||||
initializerClass: $discoveredAttribute->className,
|
||||
returnType: ClassName::create($returnType),
|
||||
errorMessage: $e->getMessage(),
|
||||
exceptionClass: ClassName::create(get_class($e))
|
||||
);
|
||||
}
|
||||
|
||||
// Skip failed initializers to prevent breaking the entire application
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: Service-Initializer in optimaler Reihenfolge registrieren
|
||||
$this->registerServicesWithDependencyGraph($dependencyGraph);
|
||||
$this->registerServicesWithDependencyGraph($dependencyGraph, $failedInitializers);
|
||||
|
||||
// Phase 3: Registry für fehlgeschlagene Initializer im Container registrieren
|
||||
if (! empty($failedInitializers)) {
|
||||
$registry = new FailedInitializerRegistry(...$failedInitializers);
|
||||
$this->container->instance(FailedInitializerRegistry::class, $registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registriert Services basierend auf Dependency-Graph in optimaler Reihenfolge
|
||||
* @param FailedInitializer[] $failedInitializers
|
||||
*/
|
||||
private function registerServicesWithDependencyGraph(InitializerDependencyGraph $graph): void
|
||||
private function registerServicesWithDependencyGraph(InitializerDependencyGraph $graph, array &$failedInitializers): void
|
||||
{
|
||||
try {
|
||||
$executionOrder = $graph->getExecutionOrder();
|
||||
@@ -118,7 +139,8 @@ final readonly class InitializerProcessor
|
||||
$this->registerLazyService(
|
||||
$returnType,
|
||||
$node->getClassName(),
|
||||
$node->getMethodName()
|
||||
$node->getMethodName(),
|
||||
$failedInitializers
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -139,7 +161,8 @@ final readonly class InitializerProcessor
|
||||
$this->registerLazyService(
|
||||
$returnType,
|
||||
$node->getClassName(),
|
||||
$node->getMethodName()
|
||||
$node->getMethodName(),
|
||||
$failedInitializers
|
||||
);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
@@ -155,7 +178,8 @@ final readonly class InitializerProcessor
|
||||
$this->registerLazyService(
|
||||
$returnType,
|
||||
$node->getClassName(),
|
||||
$node->getMethodName()
|
||||
$node->getMethodName(),
|
||||
$failedInitializers
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -186,8 +210,9 @@ final readonly class InitializerProcessor
|
||||
|
||||
/**
|
||||
* Registriert einen Service lazy im Container mit Dual-Registration für Interfaces
|
||||
* @param FailedInitializer[] $failedInitializers
|
||||
*/
|
||||
private function registerLazyService(string $returnType, string $className, string $methodName): void
|
||||
private function registerLazyService(string $returnType, string $className, string $methodName, array &$failedInitializers): void
|
||||
{
|
||||
$factory = function ($container) use ($className, $methodName, $returnType) {
|
||||
try {
|
||||
@@ -222,6 +247,14 @@ final readonly class InitializerProcessor
|
||||
])
|
||||
);
|
||||
|
||||
// Track fehlgeschlagenen Initializer für spätere Diagnose
|
||||
$failedInitializers[] = new FailedInitializer(
|
||||
initializerClass: ClassName::create($className),
|
||||
returnType: ClassName::create($returnType),
|
||||
errorMessage: $e->getMessage(),
|
||||
exceptionClass: ClassName::create(get_class($e))
|
||||
);
|
||||
|
||||
// Service registration failed - continue to prevent breaking the entire application
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user