mirror of
https://github.com/KeymonSoft/jRDC-Multi.git
synced 2026-04-17 21:06:24 +00:00
- 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. - 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`). 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.
This commit is contained in:
150
Manager.bas
150
Manager.bas
@@ -259,7 +259,6 @@ Sub Handle(req As ServletRequest, resp As ServletResponse)
|
||||
Exit
|
||||
End If
|
||||
Next
|
||||
|
||||
If Main.IsAnySQLiteLoggingEnabled Then
|
||||
Main.timerLogs.Enabled = True
|
||||
sbTemp.Append($" -> Timer de limpieza de logs ACTIVADO (estado global: HABILITADO)."$).Append(" " & CRLF)
|
||||
@@ -267,11 +266,8 @@ Sub Handle(req As ServletRequest, resp As ServletResponse)
|
||||
Main.timerLogs.Enabled = False
|
||||
sbTemp.Append($" -> Timer de limpieza de logs DESHABILITADO (estado global: DESHABILITADO)."$).Append(" " & CRLF)
|
||||
End If
|
||||
|
||||
sbTemp.Append($"¡Recarga de configuración completada con éxito!"$).Append(" " & CRLF)
|
||||
|
||||
Else
|
||||
|
||||
' Si falló, restauramos el estado del timer anterior.
|
||||
If oldTimerState Then
|
||||
Main.timerLogs.Enabled = True
|
||||
@@ -279,31 +275,65 @@ Sub Handle(req As ServletRequest, resp As ServletResponse)
|
||||
End If
|
||||
sbTemp.Append($"¡ERROR: La recarga de configuración falló! Los conectores antiguos siguen activos."$).Append(" " & CRLF)
|
||||
End If
|
||||
|
||||
resp.Write(sbTemp.ToString)
|
||||
Return
|
||||
|
||||
Case "test"
|
||||
resp.ContentType = "text/plain; charset=utf-8"
|
||||
Dim sb As StringBuilder
|
||||
sb.Initialize
|
||||
sb.Append("--- INICIANDO PRUEBA DE CONECTIVIDAD A TODOS LOS POOLS CONFIGURADOS ---").Append(CRLF).Append(CRLF)
|
||||
|
||||
' Iteramos sobre la lista de DB Keys cargadas al inicio (DB1, DB2, etc.)
|
||||
For Each dbKey As String In Main.listaDeCP
|
||||
Dim success As Boolean = False
|
||||
Dim errorMsg As String = ""
|
||||
Dim con As SQL ' Conexión para la prueba
|
||||
|
||||
Try
|
||||
' 1. Obtener el RDCConnector para esta DBKey
|
||||
Dim connector As RDCConnector = Main.Connectors.Get(dbKey)
|
||||
|
||||
Try
|
||||
Dim con As SQL = Main.Connectors.Get("DB1").As(RDCConnector).GetConnection("")
|
||||
sb.Append("Connection successful." & CRLF & CRLF)
|
||||
Dim estaDB As String = ""
|
||||
Log(Main.listaDeCP)
|
||||
For i = 0 To Main.listaDeCP.Size - 1
|
||||
If Main.listaDeCP.get(i) <> "" Then estaDB = "." & Main.listaDeCP.get(i)
|
||||
sb.Append($"Using config${estaDB}.properties"$ & CRLF)
|
||||
Next
|
||||
con.Close
|
||||
resp.Write(sb.ToString)
|
||||
Catch
|
||||
resp.Write("Error fetching connection: " & LastException.Message)
|
||||
End Try
|
||||
If connector.IsInitialized = False Then
|
||||
errorMsg = "Conector no inicializado (revisa logs de AppStart)"
|
||||
Else
|
||||
' 2. Forzar la adquisición de una conexión del pool C3P0
|
||||
con = connector.GetConnection(dbKey)
|
||||
|
||||
If con.IsInitialized Then
|
||||
' 3. Si la conexión es válida, la cerramos inmediatamente para devolverla al pool
|
||||
con.Close
|
||||
success = True
|
||||
Else
|
||||
errorMsg = "La conexión devuelta no es válida (SQL.IsInitialized = False)"
|
||||
End If
|
||||
End If
|
||||
|
||||
Catch
|
||||
' Capturamos cualquier excepción (ej. fallo de JDBC, timeout de C3P0)
|
||||
errorMsg = LastException.Message
|
||||
End Try
|
||||
|
||||
If success Then
|
||||
sb.Append($"* ${dbKey}: Conexión adquirida y liberada correctamente."$).Append(CRLF)
|
||||
Else
|
||||
' Si falla, registramos el error para el administrador.
|
||||
Main.LogServerError("ERROR", "Manager.TestCommand", $"Falló la prueba de conectividad para ${dbKey}: ${errorMsg}"$, dbKey, "test_command", req.RemoteAddress)
|
||||
sb.Append($"[FALLO] ${dbKey}: ERROR CRÍTICO al obtener conexión. Mensaje: ${errorMsg}"$).Append(CRLF)
|
||||
End If
|
||||
Next
|
||||
|
||||
sb.Append(CRLF).Append("--- FIN DE PRUEBA DE CONEXIONES ---").Append(CRLF)
|
||||
|
||||
' Mantenemos la lista original de archivos de configuración cargados (esto es informativo)
|
||||
sb.Append(CRLF).Append("Archivos de configuración cargados:").Append(CRLF)
|
||||
For Each item As String In Main.listaDeCP
|
||||
Dim configName As String = "config"
|
||||
If item <> "DB1" Then configName = configName & "." & item
|
||||
sb.Append($" -> Usando ${configName}.properties"$).Append(CRLF)
|
||||
Next
|
||||
|
||||
resp.Write(sb.ToString)
|
||||
Return
|
||||
|
||||
Case "rsx", "rpm2", "revivebow", "restartserver"
|
||||
resp.ContentType = "text/plain; charset=utf-8"
|
||||
Dim batFile As String
|
||||
@@ -358,7 +388,85 @@ Sub Handle(req As ServletRequest, resp As ServletResponse)
|
||||
resp.Write("Error: El mapa de bloqueo no está inicializado.")
|
||||
End If
|
||||
Return
|
||||
Case "getconfiginfo"
|
||||
resp.ContentType = "text/plain; charset=utf-8"
|
||||
Dim sbInfo As StringBuilder
|
||||
sbInfo.Initialize
|
||||
|
||||
' sbInfo.Append($"--- CONFIGURACIÓN ACTUAL DEL SERVIDOR jRDC2-Multi ($DateTime{DateTime.Now}) ---"$).Append(CRLF).Append(CRLF)
|
||||
|
||||
Dim allKeys As List
|
||||
allKeys.Initialize
|
||||
allKeys.AddAll(Main.listaDeCP) ' DB1, DB2, ...
|
||||
sbInfo.Append("======================================================================").Append(CRLF)
|
||||
sbInfo.Append($"=== CONFIGURACIÓN jRDC2-Multi V$1.2{Main.VERSION} (ACTIVA) ($DateTime{DateTime.Now}) ==="$).Append(CRLF)
|
||||
sbInfo.Append("======================================================================").Append(CRLF).Append(CRLF)
|
||||
|
||||
' ***** GLOSARIO DE PARÁMETROS CONFIGURABLES *****
|
||||
sbInfo.Append("### GLOSARIO DE PARÁMETROS PERMITIDOS EN CONFIG.PROPERTIES ###").Append(CRLF)
|
||||
sbInfo.Append("--------------------------------------------------").Append(CRLF)
|
||||
|
||||
sbInfo.Append("DriverClass: Clase del driver JDBC (ej: oracle.jdbc.driver.OracleDriver).").Append(CRLF)
|
||||
sbInfo.Append("JdbcUrl: URL de conexión a la base de datos (IP, puerto, servicio).").Append(CRLF)
|
||||
sbInfo.Append("User/Password: Credenciales de acceso a la BD.").Append(CRLF)
|
||||
sbInfo.Append("ServerPort: Puerto de escucha del servidor B4J (solo lo toma de config.properties).").Append(CRLF)
|
||||
sbInfo.Append("Debug: Si es 'true', los comandos SQL se recargan en cada petición (DESHABILITADO, USAR COMANDO RELOAD).").Append(CRLF)
|
||||
sbInfo.Append("parameterTolerance: Define si se recortan (1) o se rechazan (0) los parámetros SQL sobrantes a los requeridos por el query.").Append(CRLF)
|
||||
sbInfo.Append("enableSQLiteLogs: Control granular. Habilita (1) o deshabilita (0) la escritura de logs en users.db para esta DB.").Append(CRLF)
|
||||
sbInfo.Append("InitialPoolSize: Conexiones que el pool establece al iniciar (c3p0).").Append(CRLF)
|
||||
sbInfo.Append("MinPoolSize: Mínimo de conexiones inactivas que se mantendrán.").Append(CRLF)
|
||||
sbInfo.Append("MaxPoolSize: Máximo de conexiones simultáneas permitido.").Append(CRLF)
|
||||
sbInfo.Append("AcquireIncrement: Número de conexiones nuevas que se adquieren en lote al necesitar más.").Append(CRLF)
|
||||
sbInfo.Append("MaxIdleTime: Tiempo máximo (segundos) de inactividad antes de cerrar una conexión.").Append(CRLF)
|
||||
sbInfo.Append("MaxConnectionAge: Tiempo máximo de vida (segundos) de una conexión.").Append(CRLF)
|
||||
sbInfo.Append("CheckoutTimeout: Tiempo máximo de espera (milisegundos) por una conexión disponible.").Append(CRLF)
|
||||
sbInfo.Append(CRLF)
|
||||
|
||||
For Each dbKey As String In allKeys
|
||||
|
||||
' --- COMIENZA EL DETALLE POR CONECTOR ---
|
||||
|
||||
Dim connector As RDCConnector = Main.Connectors.Get(dbKey)
|
||||
|
||||
sbInfo.Append("--------------------------------------------------").Append(CRLF).Append(CRLF)
|
||||
sbInfo.Append($"---------------- ${dbKey} ------------------"$).Append(CRLF).Append(CRLF)
|
||||
sbInfo.Append("--------------------------------------------------").Append(CRLF).Append(CRLF)
|
||||
If connector.IsInitialized Then
|
||||
Dim configMap As Map = connector.config
|
||||
|
||||
sbInfo.Append($"DriverClass: ${configMap.GetDefault("DriverClass", "N/A")}"$).Append(CRLF)
|
||||
sbInfo.Append($"JdbcUrl: ${configMap.GetDefault("JdbcUrl", "N/A")}"$).Append(CRLF)
|
||||
sbInfo.Append($"User: ${configMap.GetDefault("User", "N/A")}"$).Append(CRLF)
|
||||
sbInfo.Append($"ServerPort: ${configMap.GetDefault("ServerPort", "N/A")}"$).Append(CRLF).Append(CRLF)
|
||||
|
||||
sbInfo.Append("--- CONFIGURACIÓN DEL POOL (C3P0) ---").Append(CRLF)
|
||||
sbInfo.Append($"InitialPoolSize: ${configMap.GetDefault("InitialPoolSize", 3)}"$).Append(CRLF)
|
||||
sbInfo.Append($"MinPoolSize: ${configMap.GetDefault("MinPoolSize", 2)}"$).Append(CRLF)
|
||||
sbInfo.Append($"MaxPoolSize: ${configMap.GetDefault("MaxPoolSize", 5)}"$).Append(CRLF)
|
||||
sbInfo.Append($"AcquireIncrement: ${configMap.GetDefault("AcquireIncrement", 5)}"$).Append(CRLF)
|
||||
sbInfo.Append($"MaxIdleTime (s): ${configMap.GetDefault("MaxIdleTime", 300)}"$).Append(CRLF)
|
||||
sbInfo.Append($"MaxConnectionAge (s): ${configMap.GetDefault("MaxConnectionAge", 900)}"$).Append(CRLF)
|
||||
sbInfo.Append($"CheckoutTimeout (ms): ${configMap.GetDefault("CheckoutTimeout", 60000)}"$).Append(CRLF).Append(CRLF)
|
||||
|
||||
sbInfo.Append("--- COMPORTAMIENTO ---").Append(CRLF)
|
||||
sbInfo.Append($"Debug (Recarga Queries - DESHABILITADO): ${configMap.GetDefault("Debug", "false")}"$).Append(CRLF)
|
||||
|
||||
' Lectura explícita de las nuevas propiedades, asegurando un Int.
|
||||
Dim tolerance As Int = configMap.GetDefault("parameterTolerance", 0).As(Int)
|
||||
sbInfo.Append($"ParameterTolerance: ${tolerance} (0=Estricto, 1=Habilitado)"$).Append(CRLF)
|
||||
|
||||
Dim logsEnabled As Int = configMap.GetDefault("enableSQLiteLogs", 1).As(Int)
|
||||
sbInfo.Append($"EnableSQLiteLogs: ${logsEnabled} (0=Deshabilitado, 1=Habilitado)"$).Append(CRLF)
|
||||
|
||||
sbInfo.Append(CRLF)
|
||||
|
||||
Else
|
||||
sbInfo.Append($"ERROR: Conector ${dbKey} no inicializado o falló al inicio."$).Append(CRLF).Append(CRLF)
|
||||
End If
|
||||
Next
|
||||
|
||||
resp.Write(sbInfo.ToString)
|
||||
Return
|
||||
Case Else
|
||||
resp.ContentType = "text/plain; charset=utf-8"
|
||||
resp.SendError(404, $"Comando desconocido: '{Command}'"$)
|
||||
|
||||
Reference in New Issue
Block a user