tryLoadCompiledContainer($basePath, $collector); // if ($optimizedContainer !== null) { // return $optimizedContainer; // } // Fallback to fresh container bootstrap return $this->bootstrapFreshContainer($basePath, $collector); } /** * Try to load compiled container if valid */ private function tryLoadCompiledContainer( string $basePath, PerformanceCollectorInterface $collector ): ?Container { try { $cacheDir = sys_get_temp_dir() . '/framework-cache'; $compiledPath = ContainerCompiler::getCompiledContainerPath($cacheDir); // Quick existence check first if (! file_exists($compiledPath)) { return null; } // Create temporary fresh container to validate against $tempContainer = $this->createFreshContainer($basePath, $collector); // Create compiler for validation $reflectionProvider = new CachedReflectionProvider(); $dependencyResolver = new DependencyResolver($reflectionProvider, $tempContainer); $compiler = new ContainerCompiler($reflectionProvider, $dependencyResolver); // Validate compiled container if (! $compiler->isCompiledContainerValid($tempContainer, $compiledPath)) { return null; // Invalid, will trigger fresh bootstrap } // Load and return compiled container $compiledContainer = ContainerCompiler::load($compiledPath); // Add runtime instances that can't be compiled $this->addRuntimeInstances($compiledContainer, $basePath, $collector); return $compiledContainer; } catch (\ParseError $e) { // Parse error in compiled container - delete cache and fallback $this->clearCompiledCache($compiledPath); error_log("Compiled container has syntax error, deleted cache: " . $e->getMessage()); return null; } catch (\Exception $e) { // Any other error means we fallback to fresh container return null; } } /** * Bootstrap fresh container and compile for next request */ private function bootstrapFreshContainer( string $basePath, PerformanceCollectorInterface $collector ): Container { $container = $this->createFreshContainer($basePath, $collector); // Compile for next request (async in production) $this->compileContainerAsync($container); return $container; } /** * Create fresh container with all bindings */ private function createFreshContainer( string $basePath, PerformanceCollectorInterface $collector ): DefaultContainer { // Use the existing container or create new DefaultContainer $container = $this->container instanceof DefaultContainer ? $this->container : new DefaultContainer(); $this->addRuntimeInstances($container, $basePath, $collector); $this->autowire($container); return $container; } /** * Add instances that must be created at runtime */ private function addRuntimeInstances( Container $container, string $basePath, PerformanceCollectorInterface $collector ): void { // Core services that need runtime data $container->instance(Logger::class, new DefaultLogger()); $container->instance(PerformanceCollectorInterface::class, $collector); $container->instance(Cache::class, new CacheInitializer($collector, $container)()); $container->instance(PathProvider::class, new PathProvider($basePath)); $container->instance(ResponseEmitter::class, new ResponseEmitter()); $container->instance(Clock::class, new SystemClock()); // TEMPORARY FIX: Manual RequestFactory binding until Discovery issue is resolved $container->singleton(\App\Framework\Http\Request::class, function ($container) { error_log("ContainerBootstrapper: Creating Request singleton"); // Get Cache from container (it was just registered above) $frameworkCache = $container->get(\App\Framework\Cache\Cache::class); $parserCache = new \App\Framework\Http\Parser\ParserCache($frameworkCache); $parser = new \App\Framework\Http\Parser\HttpRequestParser($parserCache); $factory = new \App\Framework\Http\RequestFactory($parser); error_log("ContainerBootstrapper: About to call factory->createFromGlobals()"); $request = $factory->createFromGlobals(); error_log("ContainerBootstrapper: Request created successfully"); return $request; }); } /** * Compile container asynchronously for next request */ private function compileContainerAsync(DefaultContainer $container): void { try { $cacheDir = sys_get_temp_dir() . '/framework-cache'; $compiledPath = ContainerCompiler::getCompiledContainerPath($cacheDir); $reflectionProvider = new CachedReflectionProvider(); $dependencyResolver = new DependencyResolver($reflectionProvider, $container); $compiler = new ContainerCompiler($reflectionProvider, $dependencyResolver); // Compile (async in production, sync in development) #$isProduction = $this->config->get('app.environment') === 'production'; $isProduction = false; if ($isProduction) { $compiler->compileAsync($container, $compiledPath); } else { $compiler->compile($container, $compiledPath); } } catch (\Exception $e) { // Compilation errors should not break the application // In production, log this error } } private function autowire(Container $container): void { // Discovery service bootstrapping $clock = $container->get(Clock::class); $bootstrapper = new DiscoveryServiceBootstrapper($container, $clock); $results = $bootstrapper->bootstrap(); } /** * Clear compiled container cache files */ private function clearCompiledCache(string $compiledPath): void { try { // Delete the compiled container file if (file_exists($compiledPath)) { @unlink($compiledPath); } // Also clear related cache directory if it exists $cacheDir = dirname($compiledPath); if (is_dir($cacheDir)) { // Clear all cache files in the directory $files = glob($cacheDir . '/*'); foreach ($files as $file) { if (is_file($file)) { @unlink($file); } } } } catch (\Throwable $e) { // Ignore cache cleanup errors, just log them error_log("Error clearing compiled cache: " . $e->getMessage()); } } }