mirror of
https://github.com/KeymonSoft/jRDC-MultiDB-Hikari.git
synced 2026-04-17 12:56:23 +00:00
- feat(arquitectura): Consolidación de estabilidad y diagnóstico. - refactor: Arquitectura de base de datos local y políticas de logs. - arch(sqlite): Aislamiento total de las conexiones SQLite en SQL_Auth y SQL_Logs. Esto protege las operaciones de autenticación críticas de la alta carga de I/O generada por el subsistema de logs. - feat(logs): Implementación de modo de almacenamiento flexible para logs (disco o en memoria), mejorando la capacidad de testing. - refactor(logs): Se estandariza el límite de retención de registros a 10,000 para todas las tablas de logs, y se renombra la subrutina de limpieza a borraArribaDe10000Logs.
245 lines
30 KiB
QBasic
245 lines
30 KiB
QBasic
B4J=true
|
|
Group=Default Group
|
|
ModulesStructureVersion=1
|
|
Type=StaticCode
|
|
Version=10.3
|
|
@EndOfDesignText@
|
|
' ########################################
|
|
' ##### HISTORIAL DE CAMBIOS #####
|
|
' ########################################
|
|
|
|
Sub Process_Globals
|
|
|
|
' - VERSION X.XX.XX (cambios a implementar)
|
|
' - Agregar una forma de probar con carga el servidor.
|
|
' - Agregar algun tipo de autenticación, posiblemente con tokens ... se podria poner
|
|
' en el config.properties un token de conexion y solo las peticiones que lo incluyan sean atendidas, o
|
|
' guardar los tokens en la BD sqlite.
|
|
' - Si se implementan los tokens, se podrian ligar los tokens con el "*" de CORS, y los tokens definirian
|
|
' los dominios permitidos.
|
|
' - Ej: token:1224abcd5678fghi, dominio:"keymon.net"
|
|
' - Ej: token:4321abcd8765fghi, dominio:"*"
|
|
' - Que en el reporte de "Queries lentos" se pueda especificar de cuanto tiempo, ahorita esta solo de la ultima hora, pero que se pueda seleccionar desde una
|
|
' lista, por ejemplo 15, 30, 45 y 60 minutos antes.
|
|
|
|
- VERSION 5.10.27
|
|
feat(arquitectura): Consolidación de estabilidad y diagnóstico.
|
|
|
|
refactor: Arquitectura de base de datos local y políticas de logs.
|
|
|
|
- arch(sqlite): Aislamiento total de las conexiones SQLite en SQL_Auth y SQL_Logs. Esto protege las operaciones de autenticación críticas de la alta carga de I/O generada por el subsistema de logs.
|
|
- feat(logs): Implementación de modo de almacenamiento flexible para logs (disco o en memoria), mejorando la capacidad de testing.
|
|
- fix(manager): Se corrige la inestabilidad del reporte /slowqueries (NumberFormatException) al omitir parámetros y se habilita el ordenamiento dinámico de las columnas.
|
|
- refactor(logs): Se estandariza el límite de retención de registros a 10,000 para todas las tablas de logs, y se renombra la subrutina de limpieza a borraArribaDe10000Logs.
|
|
|
|
' - VERSION: 5.10.25
|
|
' - refactor(hikari): Migración completa de C3P0 a HikariCP. Corrección de Hot-Swap y estabilización de la concurrencia.
|
|
' - El cambio principal es la sustitución del pool de conexiones C3P0 por HikariCP (versión 4.0.3). Esto resuelve problemas de estabilidad y reduce el overhead de sincronización, moviendo la infraestructura de pooling a un estándar industrial más robusto y rápido.
|
|
' - Los cambios funcionales y arquitectónicos más relevantes son:
|
|
' 1. Estabilización de Concurrencia (Segregación de Locks):
|
|
' 2. Monitoreo y Diagnóstico Fiable:
|
|
' ◦ Métricas de Carga: Se mueve la captura de métricas de BusyConnections y TotalConnections en DBHandlerB4X.bas y DBHandlerJSON.bas para que ocurra inmediatamente después de obtener la conexión del pool (con = Connector.GetConnection(...)). Esto asegura que las métricas registradas reflejen con precisión la carga real del pool en el instante de la petición.
|
|
' ◦ Configuración del Driver: El módulo RDCConnector ahora expone en el comando /getconfiginfo las propiedades específicas del driver (e.g., cachePrepStmts) que se aplicaron vía addDataSourceProperty.
|
|
|
|
' - VERSION 5.10.15
|
|
' - fix(concurrencia): Se implementa LogCacheLock en Main.bas para proteger exclusivamente las operaciones de caché de logs. El MainConnectorsLock queda reservado solo para la administración de conectores (como el reload). Esta segregación elimina un cuello de botella crítico donde la I/O pesada de SQLite bloqueaba la gestión de los pools de conexión.
|
|
' - Se corrige un problema arquitectónico donde el MainConnectorsLock creaba un cuello de botella para la concurrencia. Anteriormente, las operaciones pesadas de I/O (escritura de lotes a SQLite) y la administración de configuración compartían el mismo lock.
|
|
' - Se introduce el LogCacheLock para proteger exclusivamente la adición y el swap atómico de las cachés de logs en memoria (QueryLogCache/ErrorLogCache).
|
|
' - El MainConnectorsLock ahora se reserva únicamente para operaciones críticas de administración, como el Hot-Swap y la modificación atómica del estado de logging (SQLiteLoggingStatusByDB).
|
|
' - Esta segregación garantiza que las operaciones de monitoreo (SSE) y la recarga dinámica de bases de datos ya no se vean afectadas por la latencia de la escritura de logs a disco.
|
|
|
|
' - VERSION 5.10.10
|
|
' - feat(config): Implementa carga dinámica y escalable de bases de datos (ya no son solo 4), permite utilizar un numero "ilimitado" de bases de datos.
|
|
' - Hay que tomar en cuenta que el número "real" de bases de datos a conectar depende de los recursos del servidor.
|
|
' - * Detección e Inicialización Dinámica: Se refactoriza el proceso de arranque del servidor para que detecte y cargue automáticamente cualquier archivo de configuración que siga el patrón estándar (`config.XXX.properties`) en el directorio de la aplicación. Esto elimina las restricciones a un conteo fijo (como el límite anterior a 4 bases de datos).
|
|
' - * Asignación de `DBKey`: La clave de conexión (DBKey) se extrae del nombre del archivo de configuración (ej., el archivo `config.cliente_A.properties` se registra como el conector "CLIENTE_A"), permitiendo nombres descriptivos arbitrarios y escalables en lugar de un esquema numérico rígido.
|
|
'
|
|
' - VERSION 5.10.01
|
|
' - Se implemento el habilitar o deshabilitar los logs SIN modificar el config.properties y SIN reiniciar el servidor, el cambio no persiste un reinicio, solo es en "memoria".
|
|
'
|
|
' - VERSION 5.09.19
|
|
' - feat(sqlite): Implementa optimización de SQLite (WAL e Índices)
|
|
' - fix(manager): Extiende el comando 'test' para verificar todos los pools de conexión configurados, se conecta a cada uno de ellos y luego los libera.
|
|
' - Mejoras al subsistema de logs y diagnóstico del servidor jRDC2-Multi.
|
|
' - Cambios principales:
|
|
' 1. Optimización del Rendimiento de SQLite (users.db):
|
|
' * Habilitación de WAL: Se implementó PRAGMA journal_mode=WAL y PRAGMA synchronous=NORMAL en `InitializeSQLiteDatabase`. Esto reduce la contención de disco y mejora el rendimiento de I/O en las escrituras transaccionales de logs por lotes.
|
|
' * Índices de logs: Se agregaron índices a las columnas `timestamp` y `duration_ms` en `query_logs`, y a `timestamp` en `errores`. Esto acelera drásticamente las operaciones de limpieza periódica (`borraArribaDe15000Logs`) y la generación de reportes de consultas lentas (`slowqueries`).
|
|
' * Se cambio el cache de los logs de 350 a 400 registros.
|
|
' * Se cambio el query de limpieza y se aumento a 30,000 registros y cada 30 minutos.
|
|
' * Se cambio el codigo que dispara el "VACUUM" para que corra cada 24 hrs.
|
|
'
|
|
' 2. Mejora del Comando de Diagnóstico 'test':
|
|
' * Se corrigió el comando `manager?command=test` para que no solo pruebe la conexión de `DB1`, sino que itere sobre `Main.listaDeCP` y fuerce la adquisición y liberación de una conexión (`GetConnection`) en *todos* los `RDCConnector` configurados (DB1, DB2, DB3, etc.).
|
|
' * La nueva lógica garantiza una prueba de vida rigurosa de cada pool C3P0, devolviendo un mensaje detallado del estado de conectividad y registrando un error crítico vía `LogServerError` si algún pool no responde.
|
|
'
|
|
' - VERSION 5.09.18
|
|
' - feat(manager): Implementa recarga granular (Hot-Swap).
|
|
' - Actualiza manager.html para solicitar la DB Key a recargar (ej: DB2).
|
|
' - Se modifica Manager.bas para leer este parámetro y ejecutar el Hot-Swap de forma atómica solo en el pool de conexión especificado, lo cual mejora la eficiencia y la disponibilidad del servicio.
|
|
'
|
|
' - VERSION 5.09.17
|
|
' - fix(handlers, logs): Reporte robusto de AffectedRows (simbólico) y limpieza de tabla de errores
|
|
' - Aborda dos problemas críticos para la estabilidad y fiabilidad del servidor: el manejo del conteo de filas afectadas en DMLs y la gestión del crecimiento de la tabla de logs de errores.
|
|
' - Cambios Principales:
|
|
' 1. Fix AffectedRows (ExecuteBatch V1 y DBHandlerJSON): Dada la imposibilidad de capturar el conteo de filas afectadas real (Null) de forma segura o la falla total en tiempo de ejecución (Method: ExecNonQuery2 not matched) al usar reflexión, se revierte la lógica a la llamada directa de ExecNonQuery2. Si el comando DML se ejecuta sin lanzar una excepción SQL, se reporta simbólicamente '1' fila afectada al cliente (en el Protocolo V1 y en la respuesta JSON para executecommand) para confirmar el éxito de la operación.
|
|
' 2. Limpieza de Tabla de Errores: Se corrigió la subrutina Main.borraArribaDe15000Logs para incluir la tabla `errores` en la limpieza periódica. Esto asegura que el log de errores no crezca indefinidamente, manteniendo solo los 15,000 registros más recientes y realizando la optimización de espacio en disco con `vacuum`.
|
|
'
|
|
' - VERSION 5.09.16.2
|
|
' - feat(logs): Implementación de Cacheo y Escritura Transaccional en Lotes.
|
|
' - Implementa la funcionalidad de cacheo de logs en memoria y escritura transaccional para reducir el overhead de E/S de disco en SQLite.
|
|
' - Cambios principales:
|
|
' 1. Refactorización de LogQueryPerformance y LogServerError para que solo almacenen logs en las cachés globales (QueryLogCache y ErrorLogCache).
|
|
' 2. Introducción de WriteQueryLogsBatch y WriteErrorLogsBatch, que vacían las cachés y realizan la inserción a SQLite dentro de una única transacción atómica (`BeginTransaction`/`TransactionSuccessful`), disparada por umbral (`LOG_CACHE_THRESHOLD`) o periódicamente por `TimerLogs_Tick`.
|
|
' 3. Corrección del manejo de objetos List en las rutinas de lote (Write*LogsBatch): Se implementó la copia explícita de contenido (`List.AddAll`) dentro del bloqueo (`MainConnectorsLock`) para asegurar que el lote mantenga sus registros, resolviendo el problema de tamaño cero causado por la asignación de referencias.
|
|
'
|
|
' - VERSION 5.09.16.1
|
|
' - Detalle de Comandos Batch: Se modificó DBHandlerB4X.bas (ExecuteBatch V1 y ExecuteBatch2 V2) para que, en lotes de tamaño 1, el Log retorne el nombre específico del comando (queryName) en lugar del genérico "batch (size=1)". Esto asegura que el query_logs registre la query exacta junto a su dbKey.
|
|
' - Timestamp Legible en SQLite: Se añade la columna timestamp_text_local a la tabla query_logs (incluyendo la lógica de migración en Main.InitializeSQLiteDatabase) y se actualiza Main.LogQueryPerformance para calcular e insertar el tiempo en formato yyyy/mm/dd HH:mm:ss.sss. Esto permite la inspección directa de la base de datos Sin necesidad de conversiones, mejorando la usabilidad para el análisis de rendimiento.
|
|
'
|
|
' - Versión: 5.09.16
|
|
' - feat: Implementa control de logs de SQLite granular por DBKey y corrige la concurrencia del Timer en Hot-Swap.
|
|
' - Este commit introduce una mejora crucial en el rendimiento y la flexibilidad del servidor al permitir el control detallado del registro de logs en SQLite (users.db) por cada base de datos configurada (DB1, DB2, etc.).
|
|
' - Cambios Principales y Beneficios:
|
|
' 1. Control Granular de Logs: Se reemplazó el flag de control global de logs por un mapa (SQLiteLoggingStatusByDB), permitiendo al administrador deshabilitar el costoso proceso de escritura de query_logs y errores para bases de datos específicas mediante la propiedad enableSQLiteLogs en sus archivos .properties correspondientes.
|
|
' 2. Estabilización del Timer y Hot-Swap:
|
|
' ◦ Se corrigió un problema de concurrencia y estado asegurando que timerLogs se inicialice incondicionalmente, resolviendo el error IllegalStateException: Interval must be larger than 0 que ocurría durante el reload.
|
|
' ◦ El Timer de limpieza (borraArribaDe15000Logs y VACUUM) ahora se activa solo si al menos una base de datos tiene el logging habilitado (IsAnySQLiteLoggingEnabled), minimizando el overhead de E/S de disco cuando los logs no se requieren.
|
|
' 3. Recarga Dinámica de Estado: El comando manager?command=reload ahora lee la configuración enableSQLiteLogs de todos los conectores nuevos y actualiza atómicamente el estado global de logs, aplicando los cambios Sin requerir un reinicio del servidor.
|
|
'
|
|
' - VERSION 5.09.16
|
|
' feat: Implementa tolerancia de parámetros configurable y mejora estabilidad general del servidor.
|
|
' La tolerancia de parametros permite que si un query requiere 3 parametros y se mandan 4, NO mande un error,
|
|
' solo manda a la base de datos los parametros correctos y tira los extras, y guarda una "ADVERTENCIA" en el Log de errores.
|
|
'
|
|
' Este commit introduce la funcionalidad de `parameterTolerance` configurable y aborda varias mejoras críticas para la estabilidad y eficiencia del jRDC2-Multi.
|
|
' Principales cambios y beneficios:
|
|
' - **Tolerancia de Parámetros**: Añade la propiedad `parameterTolerance` en `config.properties` para controlar el manejo de parámetros de más. Cuando está habilitada, recorta los parámetros excesivos; si está deshabilitada (modo estricto, por defecto), genera un error, aumentando la robustez de la validación.
|
|
' - **Inicialización Multi-DB Confiable**: Corrige la lógica de inicialización en `Main.AppStart` para `RDCConnector` de DB3 y DB4, asegurando que cada base de datos tenga su propio *pool* de conexiones correctamente configurado.
|
|
' - **Optimización de Ejecución SQL**: Elimina llamadas duplicadas a `ExecQuery2` y `ExecNonQuery2` en `DBHandlerB4X.bas`, garantizando que solo los parámetros validados se utilicen y evitando ejecuciones redundantes en la base de datos.
|
|
' - **Refactorización y Limpieza**: Se eliminó la declaración duplicada de `ActiveRequestsCountByDB` en `Main.bas` y la subrutina `Handle0` obsoleta en `Manager.bas`, mejorando la claridad y mantenibilidad del código.
|
|
'
|
|
' - VERSION 5.09.15
|
|
' 1. **Nuevas Funcionalidades en el Panel de Administración (Manager):**
|
|
' * Se añadió el comando `slowqueries` al `Manager` para permitir la visualización de las 20 consultas más lentas registradas en la tabla `query_logs` de SQLite.
|
|
' * Se mejoró el comando `totalcon` en `Manager.bas` para mostrar estadísticas detalladas de *todos* los pools de conexión C3P0 configurados, obteniendo métricas en tiempo real (TotalConnections, BusyConnections, IdleConnections, etc.) de cada `RDCConnector`.
|
|
' * Beneficio: Mayor visibilidad y control proactivo sobre el rendimiento y el uso de recursos del servidor desde la interfaz de administración.
|
|
' 2. **Optimización de la Gestión de Logs (`query_logs`):**
|
|
' * Se implementó un `Public timerLogs As Timer` en `Main.bas`, que se inicializa en `AppStart` y ejecuta periódicamente (cada 10 minutos) la subrutina `borraArribaDe15000Logs`.
|
|
' * La subrutina `borraArribaDe15000Logs` recorta la tabla `query_logs` en `users.db` para mantener solo los 15,000 registros más recientes, y luego realiza un `vacuum` para optimizar el espacio en disco utilizado por la base de datos SQLite.
|
|
' * Beneficio: Prevención del crecimiento excesivo de la base de datos de logs de rendimiento, manteniendo un historial manejable y optimizando el uso del almacenamiento a largo plazo.
|
|
'
|
|
' - VERSION 5.09.14 (Ahora consolidado en 5.09.15)
|
|
' -feat: Implementación robusta de monitoreo de pool de conexiones y peticiones activas
|
|
' -Este commit resuelve problemas críticos en el monitoreo del pool de conexiones (C3P0) y el conteo de peticiones activas por base de datos, mejorando significativamente la visibilidad y fiabilidad del rendimiento del servidor jRDC2-Multi.
|
|
' -Problemas Identificados y Resueltos:
|
|
' 1. **Métricas de `BusyConnections` y `TotalConnections` inconsistentes o siempre en `0` en el `Manager` y `query_logs`:**
|
|
' * **Problema**: Anteriormente, la métrica `busy_connections` en `query_logs` a menudo reportaba `0` o no reflejaba el estado real. De manera similar, el panel de `Manager?command=totalcon` consistentemente mostraba `BusyConnections: 0` y `TotalConnections` estancadas en `InitialPoolSize`, a pesar de que Oracle sí reportaba conexiones activas. Esto generaba confusión sobre el uso real y la expansión del pool.
|
|
' * **Solución**: Se modificó la lógica en los *handlers* (`DBHandlerJSON.bas` y `DBHandlerB4X.bas`) para capturar la métrica `BusyConnections` directamente del pool de C3P0 **inmediatamente después de que el *handler* adquiere una conexión** (`con = Connector.GetConnection(finalDbKey)`). Este valor se pasa explícitamente a la subrutina `Main.LogQueryPerformance` para su registro en `query_logs` y para ser consumido por `Manager.bas` a través de `RDCConnector.GetPoolStats`. Esto garantiza que el valor registrado y reportado refleje con precisión el número de conexiones activas en el instante de su adquisición. Pruebas exhaustivas confirmaron que C3P0 sí reporta conexiones ocupadas y sí expande `TotalConnections` hasta `MaxPoolSize` cuando la demanda lo exige.
|
|
' 2. **Contador `handler_active_requests` no decrementaba correctamente:**
|
|
' * **Problema**: El contador de peticiones activas por base de datos (`GlobalParameters.ActiveRequestsCountByDB`) no mostraba un decremento consistente, resultando en un conteo que solo aumentaba o mostraba valores erráticos en los logs.
|
|
' * **Solución**:
|
|
' * Se aseguró la declaración `Public ActiveRequestsCountByDB As Map` en `GlobalParameters.bas`.
|
|
' * Se garantizó su inicialización como un `srvr.CreateThreadSafeMap` en `Main.AppStart` para un manejo concurrente seguro de los contadores.
|
|
' * En `DBHandlerJSON.bas`, la `dbKey` (obtenida del parámetro `dbx` del JSON) ahora se resuelve *antes* de incrementar el contador, asegurando que el incremento y el decremento se apliquen siempre a la misma clave de base de datos correcta.
|
|
' * Se implementó una coerción explícita a `Int` (`.As(Int)`) para todas las operaciones de lectura y escritura (`GetDefault`, `Put`) en `GlobalParameters.ActiveRequestsCountByDB`, resolviendo problemas de tipo que causaban inconsistencias y el fallo en el decremento.
|
|
' * La lógica de decremento en `Private Sub CleanupAndLog` (presente en ambos *handlers*) se hizo más robusta, verificando que el contador sea mayor que cero antes de decrementar para evitar valores negativos.
|
|
' -Beneficios de estos Cambios:
|
|
' * **Monitoreo Preciso y Fiable**: Las métricas `busy_connections` y `handler_active_requests` en `query_logs` y el panel `Manager` ahora son totalmente fiables, proporcionando una visión clara y en tiempo real del uso del pool de conexiones y la carga de peticiones activas por base de datos.
|
|
' * **Diagnóstico Mejorado**: La visibilidad interna del estado del pool de C3P0 durante las pruebas confirma que la configuración de `RDCConnector` es correcta y que el pool se expande y contrae según lo esperado por la demanda.
|
|
' * **Robustez del Código**: La gestión de contadores de peticiones activas es ahora consistente, thread-safe y a prueba de fallos de tipo, mejorando la estabilidad general del servidor bajo carga.
|
|
'
|
|
' - VERSION 5.09.13.3 (Ahora consolidado en 5.09.15)
|
|
' - Implementación de "Hot-Swap" para recarga de configuraciones de DB sin reiniciar el servidor.
|
|
' - Migración a ReentrantLock para sincronización debido a incompatibilidad con 'Sync'.
|
|
' - **Problemas Resueltos:**
|
|
' 1. **Falta de "Hot-Swap" en `reload`:** El comando `reload` en `Manager.bas` no permitía la recarga dinámica de las configuraciones de la base de datos (config.properties) sin necesidad de reiniciar el servidor. La implementación anterior simplemente re-inicializaba las instancias existentes de `RDCConnector` in-situ, sin liberar los recursos de los pools de conexión anteriores, lo cual era ineficiente y propenso a errores.
|
|
' 2. **Ausencia de un mecanismo de cierre de pools:** No existía un método `Close` en `RDCConnector.bas` que permitiera cerrar ordenadamente los `ConnectionPool` (C3P0) y liberar las conexiones a la base de datos, lo que era crítico para un "hot-swap" limpio .
|
|
' 3. **Incompatibilidad con `Sync`:** La palabra clave `Sync` de B4X no era reconocida por el entorno de desarrollo del usuario, impidiendo su uso para la sincronización de hilos necesaria en el "hot-swap".
|
|
' 4. **Ausencia de `Finally` en B4X:** La palabra clave `Finally` (común en otros lenguajes como Java para asegurar la liberación de recursos) no está disponible directamente en B4X, lo cual planteó un desafío para garantizar la liberación del `ReentrantLock` de forma segura.
|
|
' * **Cambios Implementados:**
|
|
' * **En `Main.bas`:**
|
|
' * **Declaración de `MainConnectorsLock`:** Se añadió `Public MainConnectorsLock As JavaObject` en `Sub Process_Globals` para declarar una instancia de `java.util.concurrent.locks.ReentrantLock`, que servirá como objeto de bloqueo global para proteger el mapa `Main.Connectors`.
|
|
' * **Inicialización de `MainConnectorsLock`:** Se inicializó `MainConnectorsLock.InitializeNewInstance("java.util.concurrent.locks.ReentrantLock", Null)` en `Sub AppStart`, asegurando que el objeto de bloqueo esté listo al inicio del servidor.
|
|
' * **En `RDCConnector.bas`:**
|
|
' * **Método `Public Sub Close`:** Se añadió esta subrutina al final del módulo. Utiliza `JavaObject` para invocar `joPool.RunMethod("close", Null)` sobre la instancia subyacente de C3P0, permitiendo un cierre ordenado y la liberación de todas las conexiones del pool .
|
|
' **En `Manager.bas`:**
|
|
' * **Reemplazo completo de la lógica `If Command = "reload" Then`:**
|
|
' * **Creación de `newConnectors`:** Se crea un mapa temporal (`Dim newConnectors As Map`) para inicializar las **nuevas instancias** de `RDCConnector` con la configuración fresca de los archivos `.properties` .
|
|
' * **Preservación de `oldConnectors`:** Se almacena una referencia al mapa `Main.Connectors` actual en un nuevo mapa (`Dim oldConnectors As Map`) para tener acceso a los conectores antiguos que necesitan ser cerrados .
|
|
' * **Sincronización con `ReentrantLock`:** Para proteger la manipulación del mapa `Main.Connectors` (que es compartido por múltiples hilos), se utilizan `Main.MainConnectorsLock.RunMethod("lock", Null)` y `Main.MainConnectorsLock.RunMethod("unlock", Null)`. Esto asegura que el reemplazo del mapa sea atómico, es decir, que solo un hilo pueda acceder a `Main.Connectors` durante la lectura y la escritura .
|
|
' * **Manejo de Bloqueo Seguro sin `Finally`:** Dado que `Finally` no está disponible en B4X, se implementó un patrón con una bandera booleana (`lockAcquired`) dentro de un bloque `Try...Catch` para garantizar que `unlock()` siempre se ejecute si `lock()` fue exitoso, previniendo interbloqueos .
|
|
' * **Cierre explícito de `oldConnectors`:** Después de que los `newConnectors` reemplazan a los `oldConnectors`, se itera sobre el mapa `oldConnectors` y se llama a `oldRDC.Close` para cada conector, liberando sus recursos de base de datos de manera limpia .
|
|
' * **Validación de inicialización y control de errores:** Se agregó lógica para verificar el éxito de la inicialización de los nuevos conectores y abortar el "hot-swap" si ocurre un error crítico, manteniendo los conectores antiguos activos para evitar una interrupción del servicio .
|
|
' * **Registro detallado:** Se mejoró la salida del log HTML del `Manager` para mostrar el proceso de recarga, las estadísticas de los pools recién inicializados y el cierre de los antiguos, incluyendo JSON detallado de las métricas de C3P0 .
|
|
' • Beneficio: Estos cambios dotan al servidor jRDC2-Multi de una capacidad crítica para actualizar sus configuraciones de conexión a bases de datos en caliente, sin necesidad de reiniciar el servicio. Esto mejora la disponibilidad, simplifica el mantenimiento y previene fugas de recursos al asegurar el cierre ordenado de los pools de conexión antiguos.
|
|
'
|
|
' - VERSION 5.09.13.2 (Ahora consolidado en 5.09.15)
|
|
' - Módulo: DBHandlerJSON.bas
|
|
' - Descripción de Cambios: Manejo de Peticiones POST con Content-Type: application/json
|
|
' • Problema Identificado: La implementación anterior de DBHandlerJSON procesaba las peticiones POST esperando que el payload JSON se encontrara en el parámetro j de la URL (req.GetParameter("j")). Esto impedía la correcta lectura de peticiones POST que utilizaban Content-Type: application/json, donde el JSON se envía directamente en el cuerpo de la petición (InputStream). Como resultado, los clientes recibían un error indicando la ausencia del parámetro j .
|
|
' • Solución Implementada:
|
|
' 1. Se modificó la lógica en el método Handle para detectar explícitamente las peticiones POST con Content-Type igual a application/json.
|
|
' 2. En estos casos, el payload JSON ahora se lee directamente del InputStream de la petición (req.InputStream).
|
|
' 3. Se utilizó Bit.InputStreamToBytes(Is0) para leer el cuerpo completo de la petición a un Array de bytes, seguido de BytesToString para convertirlo en la cadena JSON.
|
|
' 4. Se añadió el cierre explícito del InputStream (Is0.Close) para asegurar la liberación de recursos .
|
|
' 5. Se corrigió el nombre de la variable Is a Is0 para evitar un conflicto con la palabra reservada Is de B4X .
|
|
' 6. Se actualizó el mensaje de error para aclarar que el JSON puede faltar tanto en el parámetro j como en el cuerpo de la petición.
|
|
' • Beneficio: Esta corrección asegura que el DBHandlerJSON sea compatible con el "Método Recomendado" de POST con application/json, mejorando la robustez y la adherencia a los estándares de las APIs web, Sin comprometer la retrocompatibilidad con el "Método Legacy" (GET con parámetro j).
|
|
'
|
|
' - VERSION 5.09.13 (Ahora consolidado en 5.09.15)
|
|
' feat: Mejora la inicialización del pool de conexiones y el soporte multi-DB.
|
|
'
|
|
' **Problemas Resueltos:**
|
|
'
|
|
' 1. **Inicialización de `TotalConnections: 0` en todos los pools:** Anteriormente, el Log mostraba 0 conexiones inicializadas para todas las bases de datos (DB1, DB2, DB3, DB4) durante `AppStart`, a pesar de que los `handlers` de `DBHandlerB4X` y `DBHandlerJSON` podían conectarse más tarde bajo demanda. Esto indicaba un fallo silencioso en la creación de conexiones iniciales por parte de C3P0.
|
|
' 2. **Configuración inconsistente de C3P0:** Parámetros críticos de C3P0 como `acquireRetryAttempts` y `breakAfterAcquireFailure` no se aplicaban correctamente al inicio, manteniendo los valores por defecto que ocultaban errores de conexión.
|
|
' 3. **`jdbcUrl` truncado/vacío:** Se observó que la `jdbcUrl` aparecía truncada o vacía en algunos logs de C3P0, indicando un problema en la carga de la configuración.
|
|
' **Cambios Implementados:**
|
|
' **En `Main.bas`:**
|
|
' * **Declaración de conectores:** Se aseguró la declaración de variables `Dim conX As RDCConnector` separadas para cada conector (con1, con2, con3, con4) para evitar conflictos de variables y asegurar la inicialización correcta.
|
|
' **En `RDCConnector.bas`:**
|
|
' * **Corrección de shadowing de `config`:** Se modificó `LoadConfigMap(DB)` para asignar directamente a la variable de clase `config` (eliminando `Dim` local), resolviendo el problema de la `jdbcUrl` truncada y asegurando que cada `RDCConnector` use su configuración específica de manera persistente.
|
|
' * **Reordenamiento y robustecimiento de `Initialize`:**
|
|
' * **Carga de `config`:** Se asegura que `config` se cargue completamente en la variable de clase antes de cualquier operación del pool.
|
|
' * **Configuración de C3P0:** Todas las propiedades del pool (incluyendo `setInitialPoolSize`, `setMinPoolSize`, `setMaxPoolSize`, `setMaxIdleTime`, etc. ahora se aplican mediante `jo.RunMethod` *inmediatamente después* de `pool.Initialize` y *antes* de que el pool intente adquirir conexiones.
|
|
' * **Forzar reportes de errores:** Se añadieron las líneas `jo.RunMethod("setAcquireRetryAttempts", Array As Object(1))` y `jo.RunMethod("setBreakAfterAcquireFailure", Array As Object(True))`. Estas son cruciales para forzar a C3P0 a lanzar una `SQLException` explícita si falla al crear las conexiones iniciales, en lugar de fallar silenciosamente.
|
|
' * **Activación forzada del pool:** Se implementó `Dim tempCon As SQL = pool.GetConnection` seguido de `tempCon.Close` dentro de un bloque `Try...Catch`. Esto obliga al pool a establecer las conexiones iniciales (`InitialPoolSize`) con la configuración ya aplicada, permitiendo la captura de errores reales si la conexión falla.
|
|
'
|
|
' - VERSION 5.09.08
|
|
' - Se agregó que se puedan configurar en el config.properties los siguientes parametros:
|
|
' - - setInitialPoolSize = 3
|
|
' - - setMinPoolSize = 2
|
|
' - - setMaxPoolSize = 5
|
|
' - Se agregaron en duro a RDConnector los siguientes parametros:
|
|
' - - setMaxIdleTime <-- Tiempo máximo de inactividad de la conexión.
|
|
' - - setMaxConnectionAge <-- Tiempo de vida máximo de una conexión.
|
|
' - - setCheckoutTimeout <-- Tiempo máximo de espera por una conexión.
|
|
' - Se agregó en el config.properties, al final del "JdbcUrl" este parametro, que le indica al servidor de Oracle
|
|
' - el nombre del cliente que se está conectando "?v$session.program=jRDC_Multi"
|
|
' - VERSION 5.09.08
|
|
' - Se cambio el codigo para que en lugar de esperar un mapa con los parametros del query y nombres de los parametros (par1, par2, etc) para definir el ordenamiento, ahora se espera una lista, y el orden de los parametros se toma directamente del orden en el que se mandan, de la misma forma que en B4A.
|
|
' - VERSION 5.09.04
|
|
' - Se cambio el nombre del handler de B4X a DBHandlerB4X.
|
|
' - Se quitaron los handlers que ya no servian.
|
|
' - VERSION 5.09.01
|
|
' - Se corrigieron errores en "Manager".
|
|
' - Se cambiaron nombres de handlers.
|
|
' - Se corrigio un error en la ruta de "www/login.html".
|
|
' - VERSION 5.08.31
|
|
' - Se corrigio que no avisaba cuando el query no requeria parametros y si se enviaban (en el JSONHandler)
|
|
' - VERSION 5.08.30
|
|
' - Se cambiaron los 4 handlers de B4A a uno solo que toma el DB de la ruta automáticamente.
|
|
' - Se agregaron validaciones del numero de parametros y si el query no los requiere o se dan de mas o de menos, manda un error especificando eso, ya no se reciben errores directos de la base de datos, esto fue tanto para B4A como para JSON.
|
|
' - Se modificó el Readme.md para incluir todos estos cambios.
|
|
' - VERSION 5.08.25
|
|
' - Se modificaron los archivos de reinicio de los servicios (servidor y Bow) y se cambio el menu del "manager" para que a seccion de "reload" incluya la liga a reinciar Bow.
|
|
' - VERSION 5.08.02
|
|
' - Se hizo un cambio para tratar de que las conexiones se "identifiquen" con Oracle y Jorge pueda saber que conexiones/recursos estamos ocupando
|
|
' - VERSION 4.11.14
|
|
' - Se agregó el parametro "setMaxPoolSize=5" para que solo genere 5 conexiones a la base de datos, antes generaba 15.
|
|
' - Se quitaron lineas previamente comentadas.
|
|
' - VERSION 4.11.09
|
|
' - Commit inicial on Nov 9, 2024
|
|
|
|
End Sub |