|
|
@@ -14,14 +14,34 @@ namespace Libs;
|
|
|
final class Database
|
|
|
{
|
|
|
private static ?\PDO $connection = null;
|
|
|
+ private static float $lastCheckedAt = 0.0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Intervalo mínimo entre validações de "liveness" da conexão.
|
|
|
+ * Dentro de uma mesma requisição (que faz várias queries em sequência),
|
|
|
+ * evita repetir o round-trip de "SELECT 1" a cada chamada de pdo().
|
|
|
+ */
|
|
|
+ private const HEALTHCHECK_INTERVAL_SECONDS = 2.0;
|
|
|
|
|
|
public static function pdo(): \PDO
|
|
|
{
|
|
|
- if (self::$connection instanceof \PDO && self::isAlive(self::$connection)) {
|
|
|
- return self::$connection;
|
|
|
+ if (self::$connection instanceof \PDO) {
|
|
|
+ $now = microtime(true);
|
|
|
+
|
|
|
+ // Só revalida a conexão se passou o intervalo mínimo desde a
|
|
|
+ // última checagem; caso contrário reaproveita direto.
|
|
|
+ if ($now - self::$lastCheckedAt < self::HEALTHCHECK_INTERVAL_SECONDS) {
|
|
|
+ return self::$connection;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (self::isAlive(self::$connection)) {
|
|
|
+ self::$lastCheckedAt = $now;
|
|
|
+ return self::$connection;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
self::$connection = self::connect();
|
|
|
+ self::$lastCheckedAt = microtime(true);
|
|
|
|
|
|
return self::$connection;
|
|
|
}
|
|
|
@@ -65,6 +85,11 @@ final class Database
|
|
|
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
|
|
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
|
|
|
\PDO::ATTR_PERSISTENT => true,
|
|
|
+ // Emula prepares no cliente: evita o round-trip extra de
|
|
|
+ // Parse/Describe server-side a cada query. Com o banco remoto
|
|
|
+ // (~160ms de latência por ida-e-volta), isso reduz o custo de
|
|
|
+ // cada query de ~3 round-trips para 1.
|
|
|
+ \PDO::ATTR_EMULATE_PREPARES => true,
|
|
|
]);
|
|
|
} catch (\PDOException $e) {
|
|
|
Logger::error('Failed to connect to database', [
|