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:
120
src/Framework/Database/Config/CacheConfig.php
Normal file
120
src/Framework/Database/Config/CacheConfig.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
50
src/Framework/Database/Config/DatabaseConfigInitializer.php
Normal file
50
src/Framework/Database/Config/DatabaseConfigInitializer.php
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
17
src/Framework/Database/Config/LoadBalancingStrategy.php
Normal file
17
src/Framework/Database/Config/LoadBalancingStrategy.php
Normal 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';
|
||||
}
|
||||
@@ -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,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
65
src/Framework/Database/Config/ReadWriteConfig.php
Normal file
65
src/Framework/Database/Config/ReadWriteConfig.php
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user