Voz del televisor y demora de RIPS: análisis de fondo de los dos "a veces"
── Voz que a veces no suena o se corta ── Dos causas nuevas, ambas intermitentes por naturaleza: 1. Defecto conocido de Chrome: si nada referencia la SpeechSynthesisUtterance, el recolector de basura puede llevársela A MITAD DE FRASE. El audio se corta en seco y 'end' no llega. Depende de cuándo pase el recolector, así que nunca se reproduce a voluntad. Cada locución queda anclada en un Set hasta terminar (_uttAncladas). 2. Tras un cancel(), en Windows y ChromeOS el motor puede quedar en pausa: speak() encola y jamás suena, sin error alguno. resume() antes de cada speak() lo destranca, y sobre un motor sano no hace nada. Y porque lo intermitente no se depura mirando la pantalla, queda una bitácora: cada intento de hablar registra voz elegida, si es local, cuánto tardó en arrancar y cómo terminó — en localStorage.tvVozLog (últimos 200) y en la tabla turnero_tv_log vía sendBeacon (endpoint log_tv.php, insert-only, eventos de lista cerrada). La próxima vez que reporten "ayer a las 10 no sonó", se consulta la tabla y se ve qué pasó exactamente. ── Servicios de RIPS que "se demoran" ── Medido en datos, no en hipótesis: la facturación en el sistema del laboratorio ocurre MIENTRAS la recepcionista atiende. La consulta a RIPS se hacía UNA sola vez, al vincular al paciente — y en 7 días, 547 de 549 registros llegaron DESPUÉS de esa única consulta. Nadie volvía a preguntar: eso es lo que se percibía como lentitud de RIPS. (El scheduler en sí tarda segundos; de paso: el reloj del equipo legado está ~1 hora atrasado, visible en hora_recepcion.) Ahora la ficha sondea cada 10 s hasta 10 minutos y se detiene al encontrar, al limpiar la ficha o al agotar los intentos. Si la recepcionista ya marcó exámenes a mano, no se le pisan: se le ofrece el banner en vez de autocargar. ── Pruebas (22, todas contra el código real extraído de las vistas) ── scripts/test_tv_voz.js 9 anclaje GC, resume(), bloqueo, voz lenta, bitácora scripts/test_rips_sondeo.js 7 reintentos, paradas, tope, sin duplicar scripts/test_rips_ventana.php 6 ventana SQL en tabla TEMPORARY, sin tocar datos Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8218daaff7
commit
a28ae82402
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* POST /modules/turnero/api/log_tv.php
|
||||
* Recibe la bitácora de voz de la pantalla del televisor (via sendBeacon).
|
||||
*
|
||||
* SIN SESIÓN, a propósito: la pantalla es un kiosco público (display_global es
|
||||
* ruta pública) y el envío es fire-and-forget. Por eso el endpoint es
|
||||
* deliberadamente sordo y estrecho:
|
||||
* - solo acepta los eventos de la lista, nada libre;
|
||||
* - recorta el detalle a 500 caracteres;
|
||||
* - no devuelve datos, solo un 204;
|
||||
* - inserta y nada más: no lee, no borra, no actualiza.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../../config/config.php';
|
||||
|
||||
http_response_code(204);
|
||||
header('Content-Type: text/plain');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') exit;
|
||||
|
||||
$raw = file_get_contents('php://input');
|
||||
if ($raw === false || strlen($raw) > 2000) exit;
|
||||
|
||||
$d = json_decode($raw, true);
|
||||
if (!is_array($d)) exit;
|
||||
|
||||
$evento = $d['e'] ?? '';
|
||||
$PERMITIDOS = ['start', 'end', 'error', 'sin_start', 'mudo'];
|
||||
if (!in_array($evento, $PERMITIDOS, true)) exit;
|
||||
|
||||
unset($d['e'], $d['t']); // el timestamp lo pone la base, no el cliente
|
||||
|
||||
try {
|
||||
$pdo = Database::getInstance()->getConnection();
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO turnero_tv_log (evento, detalle, ip, user_agent) VALUES (?, ?, ?, ?)"
|
||||
);
|
||||
$stmt->execute([
|
||||
$evento,
|
||||
mb_substr(json_encode($d, JSON_UNESCAPED_UNICODE), 0, 500),
|
||||
substr(trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '')[0]), 0, 45),
|
||||
substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 255),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// La bitácora jamás debe afectar a la pantalla
|
||||
error_log('[log_tv] ' . $e->getMessage());
|
||||
}
|
||||
Reference in New Issue
Block a user