- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
107 lines
3.8 KiB
PHP
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,
|
|
);
|
|
}
|
|
}
|