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
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Config;
use App\Framework\Core\ValueObjects\Duration;
/**
* Configuration for database second-level cache
*/
final readonly class CacheConfig
{
public Duration $defaultTtl;
public Duration $queryCacheTtl;
public function __construct(
public bool $enabled = false,
?Duration $defaultTtl = null, // 30 minutes
public int $maxSize = 10000,
public bool $queryCache = true,
?Duration $queryCacheTtl = null, // 15 minutes
public array $regions = [],
public array $enabledEntityClasses = [],
public array $disabledEntityClasses = []
) {
$this->defaultTtl = $defaultTtl ?? Duration::fromMinutes(30);
$this->queryCacheTtl = $queryCacheTtl ?? Duration::fromMinutes(15);
}
/**
* Create configuration for development environment
*/
public static function development(): self
{
return new self(
enabled: true,
defaultTtl: Duration::fromMinutes(15),
maxSize: 5000,
queryCache: true,
queryCacheTtl: Duration::fromMinutes(5),
regions: [
'User' => 'fast_changing',
'Config' => 'read_only',
'Translation' => 'read_only',
]
);
}
/**
* Create configuration for production environment
*/
public static function production(): self
{
return new self(
enabled: true,
defaultTtl: Duration::fromHours(1),
maxSize: 50000,
queryCache: true,
queryCacheTtl: Duration::fromMinutes(30),
regions: [
'User' => 'fast_changing',
'Session' => 'fast_changing',
'Config' => 'read_only',
'Translation' => 'read_only',
'Product' => 'slow_changing',
'Category' => 'slow_changing',
]
);
}
/**
* Create disabled cache configuration
*/
public static function disabled(): self
{
return new self(enabled: false);
}
/**
* Check if entity class has caching enabled
*/
public function isEntityCacheEnabled(string $entityClass): bool
{
if (! $this->enabled) {
return false;
}
// Check explicit disable list
if (in_array($entityClass, $this->disabledEntityClasses, true)) {
return false;
}
// If enabled list is specified, only cache those
if (! empty($this->enabledEntityClasses)) {
return in_array($entityClass, $this->enabledEntityClasses, true);
}
// Default to enabled if not in disabled list
return true;
}
/**
* Get cache region for entity class
*/
public function getRegionForEntity(string $entityClass): string
{
$shortName = $this->getShortClassName($entityClass);
return $this->regions[$shortName] ?? 'default';
}
private function getShortClassName(string $entityClass): string
{
$parts = explode('\\', $entityClass);
return end($parts);
}
}

View File

@@ -1,14 +1,20 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Config;
use App\Framework\Database\Driver\DriverConfig;
use App\Framework\Database\Profiling\ProfilingConfig;
final class DatabaseConfig
{
public function __construct(
public DriverConfig $driverConfig,
public PoolConfig $poolConfig,
) {}
public ReadWriteConfig $readWriteConfig,
public CacheConfig $cacheConfig = new CacheConfig(),
public ProfilingConfig $profilingConfig = new ProfilingConfig()
) {
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Config;
use App\Framework\Config\Environment;
use App\Framework\Config\EnvKey;
use App\Framework\Database\Driver\DriverConfig;
use App\Framework\Database\Driver\DriverType;
use App\Framework\DI\Initializer;
final readonly class DatabaseConfigInitializer
{
public function __construct(
private Environment $env,
) {
}
#[Initializer]
public function __invoke(): DatabaseConfig
{
$driverConfig = new DriverConfig(
driverType: DriverType::from($this->env->getString(EnvKey::DB_DRIVER, 'mysql')),
host: $this->env->getString(EnvKey::DB_HOST, 'db'),
port: $this->env->getInt(EnvKey::DB_PORT, 3306),
database: $this->env->getRequired(EnvKey::DB_DATABASE),
username: $this->env->getRequired(EnvKey::DB_USERNAME),
password: $this->env->getRequired(EnvKey::DB_PASSWORD),
charset: $this->env->getString(EnvKey::DB_CHARSET, 'utf8mb4'),
);
$poolConfig = new PoolConfig(
enabled: true,
maxConnections: 10,
minConnections: 2
);
$readWriteConfig = new ReadWriteConfig(
enabled: false, // Disabled by default, can be enabled via env vars
readConnections: []
);
return new DatabaseConfig(
driverConfig: $driverConfig,
poolConfig: $poolConfig,
readWriteConfig: $readWriteConfig,
);
}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Config;
/**
* Load balancing strategies for read replicas
*/
enum LoadBalancingStrategy: string
{
case ROUND_ROBIN = 'round_robin';
case RANDOM = 'random';
case LEAST_CONNECTIONS = 'least_connections';
case WEIGHTED = 'weighted';
case RESPONSE_TIME = 'response_time';
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Config;
@@ -9,5 +10,13 @@ final class PoolConfig
public bool $enabled,
public int $maxConnections,
public int $minConnections,
) {}
public int $connectionTimeoutSeconds = 30,
public int $healthCheckIntervalSeconds = 60,
public int $maxIdleTimeSeconds = 300,
public int $maxRetries = 3,
public bool $enableHealthChecks = true,
public bool $enableWarmup = true,
public bool $enableMetrics = true,
) {
}
}

View File

@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Config;
use App\Framework\Database\Driver\DriverConfig;
final class ReadWriteConfig
{
/**
* @param array<DriverConfig> $readConnections
*/
public function __construct(
public bool $enabled,
public array $readConnections = [],
public LoadBalancingStrategy $loadBalancingStrategy = LoadBalancingStrategy::ROUND_ROBIN,
public bool $stickySessions = false,
public int $maxLagSeconds = 5,
public bool $failoverEnabled = true,
public int $healthCheckIntervalSeconds = 30,
public bool $readPreference = true,
public int $connectionRetryAttempts = 3
) {
}
public function hasReadReplicas(): bool
{
return ! empty($this->readConnections);
}
public function getReadReplicaCount(): int
{
return count($this->readConnections);
}
/**
* Get weight for specific read connection config
*/
public function getConnectionWeight(int $configIndex): int
{
return $this->readConnections[$configIndex]->weight ?? 100;
}
/**
* Get max connections for specific read connection config
*/
public function getMaxConnections(int $configIndex): int
{
return $this->readConnections[$configIndex]->maxConnections ?? 100;
}
/**
* Get all connection weights indexed by config position
*/
public function getAllWeights(): array
{
$weights = [];
foreach ($this->readConnections as $index => $config) {
$weights[$index] = $config->weight;
}
return $weights;
}
}