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
This commit is contained in:
@@ -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;
|
||||
// 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, $contextString);
|
||||
return DiscoveryCacheIdentifiers::discoveryKey($this->paths, $this->scanType, null);
|
||||
}
|
||||
|
||||
public function isIncremental(): bool
|
||||
|
||||
46
tests/debug/clear-discovery-cache.php
Normal file
46
tests/debug/clear-discovery-cache.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
echo "=== Clearing Discovery Cache ===\n";
|
||||
|
||||
$cacheDir = __DIR__ . '/../../storage/cache';
|
||||
if (!is_dir($cacheDir)) {
|
||||
echo "Cache directory does not exist: $cacheDir\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Find all cache files that might be related to discovery
|
||||
$patterns = [
|
||||
$cacheDir . '/discovery*',
|
||||
$cacheDir . '/*discovery*',
|
||||
$cacheDir . '/routes*',
|
||||
$cacheDir . '/attr*'
|
||||
];
|
||||
|
||||
$deletedCount = 0;
|
||||
$totalSize = 0;
|
||||
|
||||
foreach ($patterns as $pattern) {
|
||||
$files = glob($pattern);
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
$size = filesize($file);
|
||||
if (unlink($file)) {
|
||||
echo "Deleted: " . basename($file) . " (" . number_format($size) . " bytes)\n";
|
||||
$deletedCount++;
|
||||
$totalSize += $size;
|
||||
} else {
|
||||
echo "Failed to delete: " . basename($file) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($deletedCount === 0) {
|
||||
echo "No cache files found to delete.\n";
|
||||
} else {
|
||||
echo "\nDeleted $deletedCount files, freed " . number_format($totalSize) . " bytes.\n";
|
||||
}
|
||||
|
||||
echo "Cache clearing complete.\n";
|
||||
165
tests/debug/debug-discovery-context-differences.php
Normal file
165
tests/debug/debug-discovery-context-differences.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use App\Framework\Context\ContextType;
|
||||
use App\Framework\Context\ExecutionContext;
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\DI\Initializer;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
|
||||
echo "=== Discovery Context Debugging ===\n";
|
||||
|
||||
// Clear any existing caches first
|
||||
$cacheDir = __DIR__ . '/../../storage/cache';
|
||||
if (is_dir($cacheDir)) {
|
||||
$files = glob($cacheDir . '/discovery*');
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
unlink($file);
|
||||
echo "Cleared cache file: " . basename($file) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n=== Testing WEB Context ===\n";
|
||||
|
||||
// Create bootstrapper (same as web)
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: false);
|
||||
$webBootstrapper = new AppBootstrapper(__DIR__ . '/../..', $collector, $memoryMonitor);
|
||||
|
||||
// Get container from web application
|
||||
$webApp = $webBootstrapper->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";
|
||||
Reference in New Issue
Block a user