Author SHA1 Message Date
Acai ForgeandClaude Opus 5.5 d1235f2e20 Merge fix/cache-sin-redis: sin Redis la web sigue sin caché en vez de morir
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-03 15:27:20 +00:00
Acai ForgeandClaude Opus 5.5 cb03ecd239 fix(cache): sin Redis la web sigue sin caché en vez de morir
initCache() de CocoDB y AcaiAPI conectaba sin capturar errores: en un
hosting sin Redis (o sin la extensión) el plugin cache_handler tumbaba la
web entera con un RedisException. Ahora se marca como no disponible para
el resto de la petición y cacheGet/cacheSet, que ya comprobaban la
conexión, no hacen nada. Con Redis el comportamiento no cambia.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 17:08:52 +00:00
Jordan DiazandClaude Opus 5.5 80b6541e30 fix: crear uploads/webp sin carrera en funciones.php
Varias peticiones a la vez (el prerender de Astro las lanza en paralelo) veian
la carpeta sin crear y la segunda imprimia "mkdir(): File exists" delante del
JSON de action_ws, rompiendo el build de una web recien descargada.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:16:28 +00:00
Acai ForgeandClaude Opus 5.5 775ae1c95d Merge feat/uploads-columnas-miniaturas: fotos de registros con dimensiones y miniaturas
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 20:50:36 +00:00
3 changed files with 47 additions and 12 deletions
+21 -5
View File
@@ -34,6 +34,7 @@ class AcaiAPI
// ── Cache flags (mirror CocoDB interface) ───────────────────────── // ── Cache flags (mirror CocoDB interface) ─────────────────────────
public static $redis = null; public static $redis = null;
public static $redis_expireTime = 0; public static $redis_expireTime = 0;
public static $redis_no_disponible = false;
public static $force_load_cache = false; public static $force_load_cache = false;
public static $force_redis = false; public static $force_redis = false;
public static $force_redis_module = false; // consumed by external cache layer public static $force_redis_module = false; // consumed by external cache layer
@@ -647,14 +648,29 @@ class AcaiAPI
/** Connect to Redis (idempotent). */ /** Connect to Redis (idempotent). */
static function initCache() static function initCache()
{ {
// Sin Redis (hosting propio sin el servicio o sin la extensión, o el
// servicio caído) la web sigue SIN caché en vez de morir con un fatal:
// cacheGet/cacheSet ya no hacen nada si no hay conexión. Se marca para
// no reintentar en cada consulta de la misma petición.
if (self::$redis_no_disponible) return;
if (!class_exists('Redis')) {
self::$redis_no_disponible = true;
self::$redis = null;
return;
}
$redisHost = getenv('REDIS_HOST') ?: '127.0.0.1'; $redisHost = getenv('REDIS_HOST') ?: '127.0.0.1';
$redisPort = (int)(getenv('REDIS_PORT') ?: 6379); $redisPort = (int)(getenv('REDIS_PORT') ?: 6379);
if (!self::$redis) { try {
self::$redis = new Redis(); if (!self::$redis) self::$redis = new Redis();
self::$redis->connect($redisHost, $redisPort); if (!self::$redis->isConnected() && !self::$redis->connect($redisHost, $redisPort)) {
} elseif (!self::$redis->isConnected()) { throw new RuntimeException("no se pudo conectar a $redisHost:$redisPort");
self::$redis->connect($redisHost, $redisPort); }
} catch (Throwable $e) {
self::$redis_no_disponible = true;
self::$redis = null;
error_log('[cache] Redis no disponible, se sigue sin caché: ' . $e->getMessage());
} }
} }
+21 -5
View File
@@ -14,6 +14,7 @@ class CocoDB
public static $trackData = []; public static $trackData = [];
public static $redis = null; public static $redis = null;
public static $redis_expireTime = 0; public static $redis_expireTime = 0;
public static $redis_no_disponible = false;
public static $force_load_cache = false; public static $force_load_cache = false;
public static $force_redis = false; public static $force_redis = false;
public static $force_redis_module = false; public static $force_redis_module = false;
@@ -1176,14 +1177,29 @@ class CocoDB
*/ */
static function initCache() static function initCache()
{ {
// Sin Redis (hosting propio sin el servicio o sin la extensión, o el
// servicio caído) la web sigue SIN caché en vez de morir con un fatal:
// cacheGet/cacheSet ya no hacen nada si no hay conexión. Se marca para
// no reintentar en cada consulta de la misma petición.
if (self::$redis_no_disponible) return;
if (!class_exists('Redis')) {
self::$redis_no_disponible = true;
self::$redis = null;
return;
}
$redisHost = getenv('REDIS_HOST') ?: '127.0.0.1'; $redisHost = getenv('REDIS_HOST') ?: '127.0.0.1';
$redisPort = (int)(getenv('REDIS_PORT') ?: 6379); $redisPort = (int)(getenv('REDIS_PORT') ?: 6379);
if (!self::$redis) { try {
self::$redis = new Redis(); if (!self::$redis) self::$redis = new Redis();
self::$redis->connect($redisHost, $redisPort); if (!self::$redis->isConnected() && !self::$redis->connect($redisHost, $redisPort)) {
} else if (!self::$redis->isConnected()) { throw new RuntimeException("no se pudo conectar a $redisHost:$redisPort");
self::$redis->connect($redisHost, $redisPort); }
} catch (Throwable $e) {
self::$redis_no_disponible = true;
self::$redis = null;
error_log('[cache] Redis no disponible, se sigue sin caché: ' . $e->getMessage());
} }
} }
+5 -2
View File
@@ -7,8 +7,11 @@ $modulosCargados = array();
$recursosCSS = array(); $recursosCSS = array();
// HASTA AUQI // HASTA AUQI
if (!file_exists(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/')) { // Sin carrera: varias peticiones a la vez (el prerender de Astro las lanza en
mkdir(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/'); // paralelo) veian la carpeta sin crear y la segunda imprimia "mkdir(): File
// exists" delante del JSON de action_ws, rompiendo el build de una web nueva.
if (!is_dir(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/')) {
@mkdir(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/', 0775, true);
} }
global $configuracionTienda; global $configuracionTienda;
$configuracionRecord = CocoDB::get("configuracion", "", null, 1); $configuracionRecord = CocoDB::get("configuracion", "", null, 1);