Files
michaelschiemer/src/Framework/ErrorBoundaries/ErrorBoundaryInitializer.php
Michael Schiemer 55a330b223 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
2025-08-11 20:13:26 +02:00

107 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\ErrorBoundaries;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\DI\Container;
use App\Framework\DI\Initializer;
use App\Framework\Logging\Logger;
/**
* Initializer for Error Boundaries
*/
final readonly class ErrorBoundaryInitializer
{
#[Initializer]
public function initialize(Container $container): void
{
// Factory
$container->bind(ErrorBoundaryFactory::class, function (Container $container) {
$logger = $container->has(Logger::class) ? $container->get(Logger::class) : null;
// Load custom route configurations from environment
$routeConfigs = $this->loadRouteConfigs();
return new ErrorBoundaryFactory(
logger: $logger,
routeConfigs: $routeConfigs
);
});
// Default boundary for general use
$container->bind(ErrorBoundary::class, function (Container $container) {
$factory = $container->get(ErrorBoundaryFactory::class);
return $factory->create('default', BoundaryConfig::database());
});
}
private function loadRouteConfigs(): array
{
$configs = [];
// Load from environment variables
// Format: ERROR_BOUNDARY_ROUTE_[ROUTE_NAME]_[SETTING] = value
foreach ($_ENV as $key => $value) {
if (! str_starts_with($key, 'ERROR_BOUNDARY_ROUTE_')) {
continue;
}
$parts = explode('_', str_replace('ERROR_BOUNDARY_ROUTE_', '', $key));
if (count($parts) < 2) {
continue;
}
$setting = array_pop($parts);
$routeName = strtolower(implode('_', $parts));
if (! isset($configs[$routeName])) {
$configs[$routeName] = [];
}
$configs[$routeName][$setting] = $this->parseConfigValue($setting, $value);
}
// Convert to BoundaryConfig objects
$boundaryConfigs = [];
foreach ($configs as $routeName => $settings) {
$boundaryConfigs[$routeName] = $this->createConfigFromArray($settings);
}
return $boundaryConfigs;
}
private function parseConfigValue(string $setting, string $value): mixed
{
return match (strtolower($setting)) {
'max_retries', 'circuit_breaker_threshold' => (int) $value,
'circuit_breaker_enabled', 'enable_metrics', 'enable_tracing' => filter_var($value, FILTER_VALIDATE_BOOLEAN),
'max_bulk_error_rate' => (float) $value,
'retry_strategy' => RetryStrategy::tryFrom(strtolower($value)) ?? RetryStrategy::EXPONENTIAL_JITTER,
'base_delay_ms' => Duration::fromMilliseconds((int) $value),
'max_delay_ms' => Duration::fromMilliseconds((int) $value),
'circuit_breaker_timeout_s' => Duration::fromSeconds((int) $value),
default => $value,
};
}
private function createConfigFromArray(array $settings): BoundaryConfig
{
return new BoundaryConfig(
maxRetries: $settings['max_retries'] ?? 3,
retryStrategy: $settings['retry_strategy'] ?? RetryStrategy::EXPONENTIAL_JITTER,
baseDelay: $settings['base_delay_ms'] ?? Duration::fromMilliseconds(100),
maxDelay: $settings['max_delay_ms'] ?? Duration::fromSeconds(5),
circuitBreakerEnabled: $settings['circuit_breaker_enabled'] ?? false,
circuitBreakerThreshold: $settings['circuit_breaker_threshold'] ?? 5,
circuitBreakerTimeout: $settings['circuit_breaker_timeout_s'] ?? Duration::fromMinutes(1),
maxBulkErrorRate: $settings['max_bulk_error_rate'] ?? 0.5,
enableMetrics: $settings['enable_metrics'] ?? true,
enableTracing: $settings['enable_tracing'] ?? false,
);
}
}