feat(di, cache): add proactive initializer discovery and caching mechanics
- Introduce `InitializerDependencyAnalyzer` to support dependency analysis during cyclic exceptions. - Add proactive initializer discovery with `InitializerCacheUpdater` for improved performance. - Integrate discovery cache updates and error handling for seamless caching of found initializers. - Extend `CyclicDependencyException` with `InitializerDependencyAnalyzer` for enhanced diagnostics and cycle analysis.
This commit is contained in:
@@ -9,6 +9,7 @@ use App\Framework\DI\Exceptions\ClassNotInstantiable;
|
||||
use App\Framework\DI\Exceptions\ClassNotResolvableException;
|
||||
use App\Framework\DI\Exceptions\ClassResolutionException;
|
||||
use App\Framework\DI\ProactiveInitializerFinder;
|
||||
use App\Framework\DI\ValueObjects\InitializerInfo;
|
||||
use App\Framework\DI\Exceptions\ContainerException;
|
||||
use App\Framework\DI\Exceptions\CyclicDependencyException;
|
||||
use App\Framework\DI\Exceptions\LazyLoadingException;
|
||||
@@ -40,6 +41,8 @@ final class DefaultContainer implements Container
|
||||
|
||||
public readonly FrameworkMetricsCollector $metrics;
|
||||
|
||||
private readonly InitializerDependencyAnalyzer $dependencyAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
private readonly InstanceRegistry $instances = new InstanceRegistry(),
|
||||
private readonly BindingRegistry $bindings = new BindingRegistry(),
|
||||
@@ -60,6 +63,7 @@ final class DefaultContainer implements Container
|
||||
fn (): array => $this->resolving
|
||||
);
|
||||
$this->metrics = new FrameworkMetricsCollector();
|
||||
$this->dependencyAnalyzer = new InitializerDependencyAnalyzer($this);
|
||||
|
||||
$this->registerSelf();
|
||||
$this->instance(ReflectionProvider::class, $this->reflectionProvider);
|
||||
@@ -144,7 +148,10 @@ final class DefaultContainer implements Container
|
||||
if (in_array($class, $this->resolving, true)) {
|
||||
throw new CyclicDependencyException(
|
||||
dependencyChain: $this->resolving,
|
||||
class: $class
|
||||
class: $class,
|
||||
code: 0,
|
||||
previous: null,
|
||||
dependencyAnalyzer: $this->dependencyAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
@@ -522,7 +529,8 @@ final class DefaultContainer implements Container
|
||||
return $container->invoker->invoke($initializerClass, $methodName);
|
||||
});
|
||||
|
||||
// TODO: Gefundenen Initializer in Discovery Cache nachtragen (später implementieren)
|
||||
// Gefundenen Initializer in Discovery Cache nachtragen
|
||||
$this->updateDiscoveryCache($initializerInfo);
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
@@ -530,4 +538,74 @@ final class DefaultContainer implements Container
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert den Discovery Cache mit einem proaktiv gefundenen Initializer
|
||||
*/
|
||||
private function updateDiscoveryCache(InitializerInfo $initializerInfo): void
|
||||
{
|
||||
try {
|
||||
$updater = $this->getCacheUpdater();
|
||||
if ($updater === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Versuche zuerst Registry aus Container zu laden
|
||||
$registry = $this->has(DiscoveryRegistry::class)
|
||||
? $this->get(DiscoveryRegistry::class)
|
||||
: null;
|
||||
|
||||
$updater->updateCache($initializerInfo, $registry);
|
||||
} catch (\Throwable $e) {
|
||||
// Silently ignore errors during cache update
|
||||
// Initializer funktioniert trotzdem, nur Cache-Update schlägt fehl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt oder erstellt einen InitializerCacheUpdater
|
||||
*/
|
||||
private function getCacheUpdater(): ?InitializerCacheUpdater
|
||||
{
|
||||
try {
|
||||
// Prüfe ob alle benötigten Abhängigkeiten verfügbar sind
|
||||
if (!$this->has(\App\Framework\Discovery\Storage\DiscoveryCacheManager::class)) {
|
||||
// Versuche DiscoveryCacheManager zu erstellen
|
||||
if (!$this->has(\App\Framework\Cache\Cache::class) ||
|
||||
!$this->has(\App\Framework\DateTime\Clock::class) ||
|
||||
!$this->has(\App\Framework\Filesystem\FileSystemService::class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache = $this->get(\App\Framework\Cache\Cache::class);
|
||||
$clock = $this->get(\App\Framework\DateTime\Clock::class);
|
||||
$fileSystemService = $this->get(\App\Framework\Filesystem\FileSystemService::class);
|
||||
|
||||
$cacheManager = new \App\Framework\Discovery\Storage\DiscoveryCacheManager(
|
||||
cache: $cache,
|
||||
clock: $clock,
|
||||
fileSystemService: $fileSystemService
|
||||
);
|
||||
} else {
|
||||
$cacheManager = $this->get(\App\Framework\Discovery\Storage\DiscoveryCacheManager::class);
|
||||
}
|
||||
|
||||
$pathProvider = $this->has(\App\Framework\Core\PathProvider::class)
|
||||
? $this->get(\App\Framework\Core\PathProvider::class)
|
||||
: new \App\Framework\Core\PathProvider(getcwd() ?: '.');
|
||||
|
||||
$clock = $this->has(\App\Framework\DateTime\Clock::class)
|
||||
? $this->get(\App\Framework\DateTime\Clock::class)
|
||||
: new \App\Framework\DateTime\SystemClock();
|
||||
|
||||
return new InitializerCacheUpdater(
|
||||
reflectionProvider: $this->reflectionProvider,
|
||||
cacheManager: $cacheManager,
|
||||
pathProvider: $pathProvider,
|
||||
clock: $clock
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user