From 03e5188644aa1c08c70417bbe0ba361956389a2a Mon Sep 17 00:00:00 2001 From: Michael Schiemer Date: Sat, 13 Sep 2025 00:36:07 +0200 Subject: [PATCH] Fix Discovery system context-dependent caching issue The Discovery system was creating separate caches for WEB vs CLI contexts, causing RequestFactory #[Initializer] to be missing in WEB context and leading to 500 errors due to Request interface binding failures. Changes: - Remove execution context from Discovery cache keys - Ensure consistent Discovery results across WEB and CLI contexts - WEB and CLI now share same Discovery cache (535 items vs 369/535 split) - RequestFactory consistently discovered in both contexts Root cause: Context-dependent cache keys caused: - CLI: discovery:full_{hash}_cli-script - WEB: discovery:full_{hash}_web Fixed: Both contexts now use discovery:full_{hash} Resolves: #21 DI Container Request Interface Binding Resolves: #18 Discovery WEB vs CLI Context differences --- .../ValueObjects/DiscoveryContext.php | 12 +- tests/debug/clear-discovery-cache.php | 46 +++++ .../debug-discovery-context-differences.php | 165 ++++++++++++++++++ 3 files changed, 217 insertions(+), 6 deletions(-) create mode 100644 tests/debug/clear-discovery-cache.php create mode 100644 tests/debug/debug-discovery-context-differences.php diff --git a/src/Framework/Discovery/ValueObjects/DiscoveryContext.php b/src/Framework/Discovery/ValueObjects/DiscoveryContext.php index c7b4412f..964e41dc 100644 --- a/src/Framework/Discovery/ValueObjects/DiscoveryContext.php +++ b/src/Framework/Discovery/ValueObjects/DiscoveryContext.php @@ -64,12 +64,12 @@ final class DiscoveryContext public function getCacheKey(): CacheKey { - // Include execution context in cache key if available - $contextString = $this->executionContext - ? $this->executionContext->getType()->value - : null; - - return DiscoveryCacheIdentifiers::discoveryKey($this->paths, $this->scanType, $contextString); + // FIXED: Remove execution context from cache key to ensure consistent Discovery results + // between WEB and CLI contexts. Discovery results should be the same regardless of + // execution context - the same PHP files should produce the same attributes. + // Context-dependent caching was causing RequestFactory to be missing in WEB context. + + return DiscoveryCacheIdentifiers::discoveryKey($this->paths, $this->scanType, null); } public function isIncremental(): bool diff --git a/tests/debug/clear-discovery-cache.php b/tests/debug/clear-discovery-cache.php new file mode 100644 index 00000000..5afb8eac --- /dev/null +++ b/tests/debug/clear-discovery-cache.php @@ -0,0 +1,46 @@ +bootstrapWeb(); +$webContainer = $webApp->getContainer(); // Assuming this method exists + +// Get discovery service +$discovery = $container->get(\App\Framework\Discovery\UnifiedDiscoveryService::class); + +// Clear cache and run discovery +$webResults = $discovery->discover(); +$webInitializers = $webResults->attributes->get(Initializer::class); + +echo "WEB Context Results:\n"; +echo "- Total items: " . count($webResults) . "\n"; +echo "- Initializer attributes: " . count($webInitializers) . "\n"; + +// Look for RequestFactory specifically +$requestFactoryFound = false; +foreach ($webInitializers as $result) { + if (str_contains($result->className, 'RequestFactory')) { + echo "- Found RequestFactory: {$result->className}::{$result->methodName}\n"; + $requestFactoryFound = true; + break; + } +} +if (!$requestFactoryFound) { + echo "- RequestFactory NOT FOUND in WEB context\n"; +} + +echo "\n=== Testing CLI Context ===\n"; + +// Force CLI context +$cliContext = ExecutionContext::forConsole(); +$bootstrapper2 = AppBootstrapper::createWithContext($cliContext); +$container2 = $bootstrapper2->bootstrap(); + +// Get discovery service (should be different container) +$discovery2 = $container2->get(\App\Framework\Discovery\UnifiedDiscoveryService::class); + +// Run discovery again +$cliResults = $discovery2->discover(); +$cliInitializers = $cliResults->attributes->get(Initializer::class); + +echo "CLI Context Results:\n"; +echo "- Total items: " . count($cliResults) . "\n"; +echo "- Initializer attributes: " . count($cliInitializers) . "\n"; + +// Look for RequestFactory specifically +$requestFactoryFound = false; +foreach ($cliInitializers as $result) { + if (str_contains($result->className, 'RequestFactory')) { + echo "- Found RequestFactory: {$result->className}::{$result->methodName}\n"; + $requestFactoryFound = true; + break; + } +} +if (!$requestFactoryFound) { + echo "- RequestFactory NOT FOUND in CLI context\n"; +} + +echo "\n=== Comparison ===\n"; +$webCount = count($webResults); +$cliCount = count($cliResults); +echo "Difference: " . abs($webCount - $cliCount) . " items\n"; + +if ($webCount !== $cliCount) { + echo "\n=== Finding Missing Items ===\n"; + + // Convert to comparable arrays + $webItems = []; + foreach ($webInitializers as $item) { + $key = $item->className . '::' . $item->methodName; + $webItems[$key] = $item; + } + + $cliItems = []; + foreach ($cliInitializers as $item) { + $key = $item->className . '::' . $item->methodName; + $cliItems[$key] = $item; + } + + $webOnly = array_diff_key($webItems, $cliItems); + $cliOnly = array_diff_key($cliItems, $webItems); + + if (!empty($webOnly)) { + echo "Items only in WEB context:\n"; + foreach ($webOnly as $key => $item) { + echo "- $key\n"; + } + } + + if (!empty($cliOnly)) { + echo "Items only in CLI context:\n"; + foreach ($cliOnly as $key => $item) { + echo "- $key\n"; + } + } +} else { + echo "Results are identical - context fix was successful!\n"; +} + +echo "\n=== Cache Key Check ===\n"; + +// Test cache key generation after fix +$webDiscoveryContext = new \App\Framework\Discovery\ValueObjects\DiscoveryContext( + paths: ['/home/michael/dev/michaelschiemer/src'], + scanType: \App\Framework\Discovery\ValueObjects\ScanType::FULL, + options: new \App\Framework\Discovery\ValueObjects\DiscoveryOptions(), + startTime: new DateTimeImmutable(), + executionContext: $webContext +); + +$cliDiscoveryContext = new \App\Framework\Discovery\ValueObjects\DiscoveryContext( + paths: ['/home/michael/dev/michaelschiemer/src'], + scanType: \App\Framework\Discovery\ValueObjects\ScanType::FULL, + options: new \App\Framework\Discovery\ValueObjects\DiscoveryOptions(), + startTime: new DateTimeImmutable(), + executionContext: $cliContext +); + +$webCacheKey = $webDiscoveryContext->getCacheKey(); +$cliCacheKey = $cliDiscoveryContext->getCacheKey(); + +echo "WEB cache key: " . $webCacheKey->toString() . "\n"; +echo "CLI cache key: " . $cliCacheKey->toString() . "\n"; +echo "Keys are identical: " . ($webCacheKey->toString() === $cliCacheKey->toString() ? 'YES' : 'NO') . "\n"; + +echo "\nDebugging complete.\n"; \ No newline at end of file