Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
@@ -1,26 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Discovery;
|
||||
|
||||
use App\Framework\Attributes\Route;
|
||||
use App\Framework\Auth\AuthMapper;
|
||||
use App\Framework\Cache\Cache;
|
||||
use App\Framework\CommandBus\CommandHandlerMapper;
|
||||
use App\Framework\Config\Configuration;
|
||||
use App\Framework\Core\AttributeMapper;
|
||||
use App\Framework\Core\Events\EventHandlerMapper;
|
||||
use App\Framework\Cache\CacheItem;
|
||||
use App\Framework\Config\AppConfig;
|
||||
use App\Framework\Config\DiscoveryConfig;
|
||||
use App\Framework\Config\TypedConfiguration;
|
||||
use App\Framework\Context\ExecutionContext;
|
||||
use App\Framework\Core\PathProvider;
|
||||
use App\Framework\Core\RouteMapper;
|
||||
use App\Framework\Database\Migration\Migration;
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\DateTime\Clock;
|
||||
use App\Framework\DI\Container;
|
||||
use App\Framework\DI\Initializer;
|
||||
use App\Framework\DI\InitializerMapper;
|
||||
use App\Framework\Discovery\Results\DiscoveryResults;
|
||||
use App\Framework\Http\HttpMiddleware;
|
||||
use App\Framework\QueryBus\QueryHandlerMapper;
|
||||
use App\Framework\View\DomProcessor;
|
||||
use App\Framework\View\StringProcessor;
|
||||
use App\Framework\Discovery\Cache\DiscoveryCacheIdentifiers;
|
||||
use App\Framework\Discovery\Factory\DiscoveryServiceFactory;
|
||||
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
||||
|
||||
/**
|
||||
* Bootstrapper für den Discovery-Service
|
||||
@@ -28,117 +24,143 @@ use App\Framework\View\StringProcessor;
|
||||
*/
|
||||
final readonly class DiscoveryServiceBootstrapper
|
||||
{
|
||||
public function __construct(private Container $container) {}
|
||||
public function __construct(
|
||||
private Container $container,
|
||||
private Clock $clock
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrapt den Discovery-Service und führt die Discovery durch
|
||||
*/
|
||||
public function bootstrap(): DiscoveryResults
|
||||
public function bootstrap(): DiscoveryRegistry
|
||||
{
|
||||
$pathProvider = $this->container->get(PathProvider::class);
|
||||
$cache = $this->container->get(Cache::class);
|
||||
$config = $this->container->get(Configuration::class);
|
||||
|
||||
// Discovery-Service erstellen
|
||||
$discoveryService = $this->createDiscoveryService($pathProvider, $cache, $config);
|
||||
// Get DiscoveryConfig if available, otherwise use defaults
|
||||
$discoveryConfig = null;
|
||||
if ($this->container->has(DiscoveryConfig::class)) {
|
||||
$discoveryConfig = $this->container->get(DiscoveryConfig::class);
|
||||
}
|
||||
|
||||
// Discovery durchführen
|
||||
$results = $discoveryService->discover();
|
||||
// Direkter Cache-Check mit expliziter toArray/fromArray Serialisierung
|
||||
$defaultPaths = [$pathProvider->getSourcePath()];
|
||||
$cacheKey = DiscoveryCacheIdentifiers::fullDiscoveryKey($defaultPaths);
|
||||
|
||||
// Ergebnisse im Container registrieren
|
||||
$this->container->singleton(DiscoveryResults::class, $results);
|
||||
$this->container->instance(UnifiedDiscoveryService::class, $discoveryService);
|
||||
|
||||
// Führe Initializers aus (Kompatibilität mit bestehendem Code)
|
||||
$this->executeInitializers($results);
|
||||
$cachedItem = $cache->get($cacheKey);
|
||||
|
||||
|
||||
if ($cachedItem->isHit) {
|
||||
// Versuche die gecachten Daten zu laden
|
||||
$cachedRegistry = null;
|
||||
|
||||
#$cachedRegistry = DiscoveryRegistry::fromArray($cachedItem->value);
|
||||
|
||||
if ($cachedItem->value instanceof DiscoveryRegistry) {
|
||||
$cachedRegistry = $cachedItem->value;
|
||||
} elseif (is_array($cachedItem->value)) {
|
||||
$cachedRegistry = DiscoveryRegistry::fromArray($cachedItem->value);
|
||||
} elseif (is_string($cachedItem->value)) {
|
||||
$cachedRegistry = DiscoveryRegistry::fromArray(json_decode($cachedItem->value, true, 512, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
|
||||
if ($cachedRegistry !== null && ! $cachedRegistry->isEmpty()) {
|
||||
$this->container->singleton(DiscoveryRegistry::class, $cachedRegistry);
|
||||
|
||||
// Initializer-Verarbeitung für gecachte Registry
|
||||
$initializerProcessor = $this->container->get(InitializerProcessor::class);
|
||||
$initializerProcessor->processInitializers($cachedRegistry);
|
||||
|
||||
return $cachedRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Vollständige Discovery durchführen
|
||||
$results = $this->performBootstrap($pathProvider, $cache, $discoveryConfig);
|
||||
|
||||
// Nach der Discovery explizit in unserem eigenen Cache-Format speichern
|
||||
$cacheItem = CacheItem::forSet(
|
||||
key: $cacheKey,
|
||||
value: $results->toArray(),
|
||||
ttl: Duration::fromHours(1)
|
||||
);
|
||||
|
||||
$cache->set($cacheItem);
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt den Discovery-Service mit der richtigen Konfiguration
|
||||
* Führt den Discovery-Prozess durch und verarbeitet die Ergebnisse
|
||||
*/
|
||||
private function performBootstrap(PathProvider $pathProvider, Cache $cache, ?DiscoveryConfig $config): DiscoveryRegistry
|
||||
{
|
||||
// Context-spezifische Discovery
|
||||
$currentContext = ExecutionContext::detect();
|
||||
$discoveryService = $this->createDiscoveryService($pathProvider, $cache, $config, $currentContext);
|
||||
|
||||
// Discovery durchführen
|
||||
$results = $discoveryService->discover();
|
||||
|
||||
// Ergebnisse im Container registrieren
|
||||
$this->container->singleton(DiscoveryRegistry::class, $results);
|
||||
$this->container->instance(UnifiedDiscoveryService::class, $discoveryService);
|
||||
|
||||
// Initializer-Verarbeitung mit dedizierter Klasse
|
||||
$initializerProcessor = $this->container->get(InitializerProcessor::class);
|
||||
$initializerProcessor->processInitializers($results);
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the modern discovery service with enhanced features using the new factory
|
||||
*/
|
||||
private function createDiscoveryService(
|
||||
PathProvider $pathProvider,
|
||||
Cache $cache,
|
||||
Configuration $config
|
||||
?DiscoveryConfig $config,
|
||||
?ExecutionContext $context = null
|
||||
): UnifiedDiscoveryService {
|
||||
$useCache = $config->get('discovery.use_cache', true);
|
||||
$showProgress = $config->get('discovery.show_progress', false);
|
||||
|
||||
// Attribute-Mapper aus Konfiguration oder Standard-Werte
|
||||
$attributeMappers = $config->get('discovery.attribute_mappers', [
|
||||
RouteMapper::class,
|
||||
EventHandlerMapper::class,
|
||||
\App\Framework\EventBus\EventHandlerMapper::class,
|
||||
QueryHandlerMapper::class,
|
||||
CommandHandlerMapper::class,
|
||||
InitializerMapper::class,
|
||||
AuthMapper::class,
|
||||
]);
|
||||
|
||||
// Ziel-Interfaces aus Konfiguration oder Standard-Werte
|
||||
$targetInterfaces = $config->get('discovery.target_interfaces', [
|
||||
AttributeMapper::class,
|
||||
HttpMiddleware::class,
|
||||
DomProcessor::class,
|
||||
StringProcessor::class,
|
||||
Migration::class,
|
||||
#Initializer::class,
|
||||
]);
|
||||
|
||||
return new UnifiedDiscoveryService(
|
||||
// Create factory
|
||||
$factory = new DiscoveryServiceFactory(
|
||||
$this->container,
|
||||
$pathProvider,
|
||||
$cache,
|
||||
$attributeMappers,
|
||||
$targetInterfaces,
|
||||
$useCache,
|
||||
$showProgress
|
||||
$this->clock
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt die gefundenen Initializers aus (Kompatibilität)
|
||||
*/
|
||||
private function executeInitializers(DiscoveryResults $results): void
|
||||
{
|
||||
$initializerResults = $results->get(Initializer::class);
|
||||
// Determine environment-based factory method
|
||||
$envType = 'production'; // Default fallback
|
||||
|
||||
#debug($initializerResults);
|
||||
|
||||
foreach ($initializerResults as $initializerData) {
|
||||
if (!isset($initializerData['class'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$className = $initializerData['class'];
|
||||
$methodName = $initializerData['method'] ?? '__invoke';
|
||||
$returnType = $initializerData['return'] ?? null;
|
||||
|
||||
#debug($initializerData);
|
||||
|
||||
|
||||
$instance = $this->container->invoker->invoke($className, $methodName);
|
||||
|
||||
|
||||
// Registriere das Ergebnis im Container falls Return-Type angegeben
|
||||
if ($returnType && $instance !== null) {
|
||||
$this->container->instance($returnType, $instance);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
debug('Fehler beim Ausführen des Initializers: ' . $e->getMessage());
|
||||
error_log("Fehler beim Ausführen des Initializers {$className}: " . $e->getMessage());
|
||||
}
|
||||
if ($this->container->has(AppConfig::class)) {
|
||||
$appConfig = $this->container->get(AppConfig::class);
|
||||
$envType = $appConfig->environment;
|
||||
} elseif ($this->container->has(TypedConfiguration::class)) {
|
||||
$typedConfig = $this->container->get(TypedConfiguration::class);
|
||||
$appConfigFromTyped = $typedConfig->appConfig();
|
||||
$envType = is_string($appConfigFromTyped->environment)
|
||||
? $appConfigFromTyped->environment
|
||||
: $appConfigFromTyped->environment->value;
|
||||
}
|
||||
|
||||
// Use factory methods which include default paths
|
||||
return match ($envType) {
|
||||
'development' => $factory->createForDevelopment(),
|
||||
'testing' => $factory->createForTesting(),
|
||||
default => $factory->createForProduction()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt einen inkrementellen Discovery-Scan durch
|
||||
* Führt einen inkrementellen Discovery-Scan durch und verarbeitet die Ergebnisse
|
||||
* mit context-aware Initializer-Verarbeitung
|
||||
*/
|
||||
public function incrementalBootstrap(): DiscoveryResults
|
||||
public function incrementalBootstrap(): DiscoveryRegistry
|
||||
{
|
||||
if (!$this->container->has(UnifiedDiscoveryService::class)) {
|
||||
if (! $this->container->has(UnifiedDiscoveryService::class)) {
|
||||
// Fallback auf vollständigen Bootstrap
|
||||
return $this->bootstrap();
|
||||
}
|
||||
@@ -147,7 +169,11 @@ final readonly class DiscoveryServiceBootstrapper
|
||||
$results = $discoveryService->incrementalDiscover();
|
||||
|
||||
// Aktualisiere Container
|
||||
$this->container->instance(DiscoveryResults::class, $results);
|
||||
$this->container->instance(DiscoveryRegistry::class, $results);
|
||||
|
||||
// Re-process initializers for current context
|
||||
$initializerProcessor = $this->container->get(InitializerProcessor::class);
|
||||
$initializerProcessor->processInitializers($results);
|
||||
|
||||
return $results;
|
||||
}
|
||||
@@ -157,11 +183,12 @@ final readonly class DiscoveryServiceBootstrapper
|
||||
*/
|
||||
public function isDiscoveryRequired(): bool
|
||||
{
|
||||
if (!$this->container->has(UnifiedDiscoveryService::class)) {
|
||||
if (! $this->container->has(UnifiedDiscoveryService::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$discoveryService = $this->container->get(UnifiedDiscoveryService::class);
|
||||
|
||||
return $discoveryService->shouldRescan();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user