mirror of
https://github.com/KeymonSoft/jRDC-MultiDB-Hikari.git
synced 2026-04-17 21:06:23 +00:00
- 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. - 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.
This commit is contained in:
155
RDCConnector.bas
155
RDCConnector.bas
@@ -4,171 +4,167 @@ ModulesStructureVersion=1
|
||||
Type=Class
|
||||
Version=4.19
|
||||
@EndOfDesignText@
|
||||
' Módulo de clase: RDCConnector
|
||||
' Esta clase gestiona el pool de conexiones a una base de datos específica.
|
||||
' REFRACTORIZADO: Usa ConnectionPoolManager y delega a HikariCP.
|
||||
' Class module: RDCConnector
|
||||
' This class manages the connection pool for a specific database.
|
||||
' Uses ConnectionPoolManager and delegates to HikariCP.
|
||||
|
||||
Sub Class_Globals
|
||||
' --- Variables globales de la clase ---
|
||||
Private pool As ConnectionPoolManager ' Usa el Manager para la modularidad
|
||||
Private MyHikariPool As HikariConnectionPool ' <-- NUEVO: Pool dedicado a esta DBKey.
|
||||
Private DebugQueries As Boolean = False ' Bandera para activar/desactivar el modo de depuración
|
||||
Public commands As Map ' Comandos SQL cargados
|
||||
' --- Class global variables ---
|
||||
Private MyHikariPool As HikariConnectionPool ' Dedicated pool for this DBKey.
|
||||
Private DebugQueries As Boolean = False ' Flag to enable/disable debug mode
|
||||
Public commands As Map ' Loaded SQL commands
|
||||
Public serverPort As Int
|
||||
Public usePool As Boolean = True
|
||||
Public config As Map ' Configuración completa (JdbcUrl, User, Password, etc.)
|
||||
Public IsParameterToleranceEnabled As Boolean ' Tolerancia a parámetros de más
|
||||
Dim driverProperties As Map ' CRÍTICO: Propiedades específicas del driver (MySQL statement caching)
|
||||
Private configLocation As String ' Ubicación del archivo de configuración
|
||||
Public config As Map ' Complete configuration (JdbcUrl, User, Password, etc.)
|
||||
Public IsParameterToleranceEnabled As Boolean ' Tolerance for extra parameters
|
||||
Dim driverProperties As Map ' Specific driver properties (MySQL statement caching)
|
||||
Private configLocation As String ' Configuration file location
|
||||
Private poolProperties As Map
|
||||
End Sub
|
||||
|
||||
' Subrutina de inicialización para el conector de una base de datos específica.
|
||||
' Initialization subroutine for a specific database connector.
|
||||
Public Sub Initialize(DB As String)
|
||||
' Nota: Este código asume que MyHikariPool ya está declarado en Class_Globals
|
||||
Dim dbKey As String = DB ' Usaremos DB como la llave
|
||||
' Note: This code assumes MyHikariPool is already declared in Class_Globals
|
||||
Dim dbKey As String = DB ' We will use DB as the key
|
||||
If DB.EqualsIgnoreCase("DB1") Then dbKey = ""
|
||||
|
||||
poolProperties.Initialize
|
||||
driverProperties.Initialize
|
||||
|
||||
' PASO 1: Cargar la configuración desde el archivo .properties correspondiente.
|
||||
config = LoadConfigMap(dbKey) ' Aseguramos la carga en la variable de clase [1]
|
||||
' Load the configuration from the corresponding .properties file.
|
||||
config = LoadConfigMap(dbKey) ' Ensure it's loaded into the class variable
|
||||
|
||||
' Lectura de la configuración de tolerancia de parámetros
|
||||
' Read the parameter tolerance configuration
|
||||
Dim toleranceSetting As Int = config.GetDefault("parameterTolerance", 0).As(Int)
|
||||
IsParameterToleranceEnabled = (toleranceSetting = 1)
|
||||
|
||||
If IsParameterToleranceEnabled Then
|
||||
Log($"RDCConnector.Initialize para ${dbKey}: Tolerancia a parámetros extras, HABILITADA."$)
|
||||
Log($"RDCConnector.Initialize for ${dbKey}: Extra parameter tolerance ENABLED."$)
|
||||
Else
|
||||
Log($"RDCConnector.Initialize para ${dbKey}: Tolerancia a parámetros extras, DESHABILITADA (modo estricto)."$)
|
||||
Log($"RDCConnector.Initialize for ${dbKey}: Extra parameter tolerance DISABLED (strict mode)."$)
|
||||
End If
|
||||
|
||||
' Bloque Try-Catch para la inicialización y configuración del pool.
|
||||
' Try-Catch block for pool initialization and configuration.
|
||||
Try
|
||||
Dim driverClass As String = config.Get("DriverClass")
|
||||
Dim jdbcUrl As String = config.Get("JdbcUrl")
|
||||
Dim aUser As String = config.Get("User")
|
||||
Dim aPassword As String = config.Get("Password")
|
||||
Dim poolType As String = "Hikari" ' Forzamos Hikari
|
||||
Dim poolType As String = "Hikari" ' Force Hikari
|
||||
|
||||
' *** INICIO DE LA LÓGICA DE PRECEDENCIA DE TAMAÑO (HIKARI) ***
|
||||
' --- Size precedence logic (HIKARI) ---
|
||||
Dim maxSizeKey As String = $"pool.${poolType.ToLowerCase}.maximumpoolsize"$
|
||||
Dim poolSizeString As String
|
||||
Dim poolSize As Int
|
||||
|
||||
' Intentamos leer el valor específico (pool.hikari.maximumpoolsize).
|
||||
' Attempt to read the specific value (pool.hikari.maximumpoolsize).
|
||||
If config.ContainsKey(maxSizeKey) Then
|
||||
poolSizeString = config.Get(maxSizeKey)
|
||||
poolSize = poolSizeString.As(Int)
|
||||
Else
|
||||
' Si no está definido, usamos el default recomendado por Hikari (10). [2]
|
||||
' If not defined, use the recommended Hikari default (10).
|
||||
poolSize = 10
|
||||
End If
|
||||
|
||||
If poolSize < 1 Then poolSize = 10 ' Mantenemos la sensatez
|
||||
Log($"RDCConnector: Usando MaximumPoolSize para ${poolType} calculado: ${poolSize}"$)
|
||||
If poolSize < 1 Then poolSize = 10 ' Keep it sensible
|
||||
Log($"RDCConnector: Using MaximumPoolSize for ${poolType} calculated: ${poolSize}"$)
|
||||
|
||||
' *** PASO 2: INICIALIZA/CREA EL POOL LOCALMENTE (Decoupling CRÍTICO) ***
|
||||
|
||||
If MyHikariPool.IsInitialized = False Then MyHikariPool.Initialize ' Inicializa el wrapper local
|
||||
|
||||
' Crea el pool subyacente (DataSource) en esta instancia dedicada. [3]
|
||||
' Initialize/Create the pool locally
|
||||
|
||||
If MyHikariPool.IsInitialized = False Then MyHikariPool.Initialize ' Initialize the local wrapper
|
||||
|
||||
' Create the underlying pool (DataSource) in this dedicated instance.
|
||||
MyHikariPool.CreatePool2(driverClass, jdbcUrl, aUser, aPassword, poolSize)
|
||||
|
||||
' PASO 3a: Cargar y filtrar SOLO las propiedades del Pool (ej. las que comienzan con 'pool.hikari.')
|
||||
' Load and filter ONLY the Pool properties (e.g., those starting with 'pool.hikari.')
|
||||
LoadPoolProperties(poolType, config)
|
||||
|
||||
' PASO 3b: Aplicar propiedades de ESTABILIDAD (Pool Properties)
|
||||
' Apply STABILITY properties (Pool Properties)
|
||||
If poolProperties.Size > 0 Then
|
||||
' Aplicación directa al pool local. [4]
|
||||
' Direct application to the local pool.
|
||||
CallSub2(MyHikariPool, "SetProperties", poolProperties)
|
||||
End If
|
||||
|
||||
' PASO 4: Cargar propiedades específicas del Driver (ej. Statement Caching)
|
||||
' Load specific Driver properties (e.g., Statement Caching)
|
||||
If config.ContainsKey("DriverShortName") Then
|
||||
LoadDriverProperties(config.Get("DriverShortName"), config)
|
||||
End If
|
||||
|
||||
' PASO 5: Aplicar propiedades de RENDIMIENTO (Driver Properties)
|
||||
' Apply PERFORMANCE properties (Driver Properties)
|
||||
If driverProperties.Size > 0 Then
|
||||
' Aplicación directa al pool local. [5]
|
||||
' Direct application to the local pool.
|
||||
CallSub2(MyHikariPool, "SetDriverProperties", driverProperties)
|
||||
Log($"RDCConnector.Initialize para ${DB}: {driverProperties.Size} propiedades del Driver aplicadas a HikariCP."$)
|
||||
Log($"RDCConnector.Initialize for ${DB}: {driverProperties.Size} Driver properties applied to HikariCP."$)
|
||||
End If
|
||||
|
||||
' PASO 6 (Prueba de vida): Forzar la creación de conexiones iniciales y verificar el estado.
|
||||
' Esto garantiza el fail-fast. [6]
|
||||
' Force initial connection creation and check status.
|
||||
' This ensures fail-fast.
|
||||
Dim tempCon As SQL = MyHikariPool.GetConnection
|
||||
If tempCon.IsInitialized Then
|
||||
tempCon.Close
|
||||
End If
|
||||
|
||||
' Cargar configuración estática en el cache global
|
||||
' Load static configuration into the global cache
|
||||
Dim dbKeyToStore As String = DB
|
||||
If dbKeyToStore = "" Then dbKeyToStore = "DB1"
|
||||
|
||||
' Almacenamos el mapa completo (configuración estática + métricas dinámicas iniciales) en el cache global.
|
||||
' GetPoolStats ahora usa MyHikariPool.
|
||||
' Store the complete map (static config + initial dynamic metrics) in the global cache.
|
||||
' GetPoolStats now uses MyHikariPool.
|
||||
Dim initialPoolStats As Map = GetPoolStats
|
||||
Main.LatestPoolStats.Put(dbKeyToStore, initialPoolStats)
|
||||
|
||||
Catch
|
||||
' Si ocurre un error durante la inicialización del pool o al forzar la conexión.
|
||||
Dim ErrorMsg As String = $"RDCConnector.Initialize para ${DB}: ERROR CRÍTICO al inicializar/forzar conexión: ${LastException.Message}"$
|
||||
' If an error occurs during pool initialization or when forcing the connection.
|
||||
Dim ErrorMsg As String = $"RDCConnector.Initialize for ${DB}: CRITICAL ERROR initializing/forcing connection: ${LastException.Message}"$
|
||||
Log(ErrorMsg)
|
||||
Main.LogServerError("ERROR", "RDCConnector.Initialize", ErrorMsg, DB, Null, Null)
|
||||
|
||||
' Si falla la inicialización, la instancia local MyHikariPool se queda inutilizada.
|
||||
' Aquí podríamos considerar la opción de llamar a MyHikariPool.ClosePool para asegurar
|
||||
' que no queden recursos parciales, aunque HikariCP debería manejarse con fail-fast.
|
||||
|
||||
' If initialization fails, the local MyHikariPool instance remains unusable.
|
||||
' We could consider calling MyHikariPool.ClosePool here to ensure
|
||||
' that no partial resources are left, although HikariCP should handle fail-fast.
|
||||
|
||||
End Try
|
||||
|
||||
' Carga los comandos SQL predefinidos de esta base de datos en el mapa global 'commandsMap' de Main.
|
||||
' Load predefined SQL commands for this database into Main's global 'commandsMap'.
|
||||
If dbKey = "" Then dbKey = "DB1"
|
||||
LoadSQLCommands(config, dbKey)
|
||||
serverPort = config.Get("ServerPort")
|
||||
|
||||
End Sub
|
||||
|
||||
' Carga el mapa de configuración
|
||||
' Load the configuration map
|
||||
Private Sub LoadConfigMap(DB As String) As Map
|
||||
Private DBX As String = ""
|
||||
If DB <> "" Then DBX = "." & DB
|
||||
Log($"RDCConnector.LoadConfigMap: Leemos el config${DBX}.properties"$)
|
||||
Log($"RDCConnector.LoadConfigMap: Reading config${DBX}.properties"$)
|
||||
Return File.ReadMap("./", "config" & DBX & ".properties")
|
||||
End Sub
|
||||
|
||||
' Obtiene la sentencia SQL completa para un comando dado.
|
||||
' Get the complete SQL statement for a given command.
|
||||
Public Sub GetCommand(DB As String, Key As String) As String
|
||||
commands = Main.commandsMap.Get(DB).As(Map)
|
||||
If commands.ContainsKey("sql." & Key) = False Then
|
||||
Dim ErrorMsg As String = $"RDCConnector.GetCommand: *** Comando no encontrado: '${Key}' para DB: '${DB}' ***"$
|
||||
Dim ErrorMsg As String = $"RDCConnector.GetCommand: *** Command not found: '${Key}' for DB: '${DB}' ***"$
|
||||
Log(ErrorMsg)
|
||||
Main.LogServerError("ERROR", "RDCConnector.GetCommand", ErrorMsg, DB, Key, Null)
|
||||
End If
|
||||
Return commands.Get("sql." & Key)
|
||||
End Sub
|
||||
|
||||
' Obtiene una conexión SQL funcional del pool de conexiones.
|
||||
' Get a functional SQL connection from the connection pool.
|
||||
Public Sub GetConnection(DB As String) As SQL
|
||||
' If DB.EqualsIgnoreCase("DB1") Then DB = ""
|
||||
' If DebugQueries Then LoadSQLCommands(LoadConfigMap(DB), DB) ' Deshabilitado por defecto. [13]
|
||||
|
||||
' Devolvemos la conexión del pool local, si está inicializado.
|
||||
' El ConnectionPoolManager ha sido removido. La delegación debe ir directamente
|
||||
' al pool dedicado de HikariCP. Esto simplifica la ruta crítica.
|
||||
If MyHikariPool.IsInitialized Then
|
||||
Return MyHikariPool.GetConnection
|
||||
Else
|
||||
Log($"ERROR: Intento de obtener conexión de DBKey ${DB}, pero MyHikariPool no está inicializado."$)
|
||||
' Devolver Null o lanzar excepción, dependiendo del manejo de errores deseado.
|
||||
Log($"ERROR: Attempt to get connection for DBKey ${DB}, but MyHikariPool is not initialized."$)
|
||||
' Es crucial retornar Null si no está inicializado para que el handler capture el error.
|
||||
Return Null
|
||||
End If
|
||||
' ANTES: Return Main.ConnectionPoolManager1.GetConnection
|
||||
End Sub
|
||||
|
||||
' Carga todos los comandos SQL del mapa de configuración en el mapa global 'commandsMap' de Main.
|
||||
' Load all SQL commands from the config map into Main's global 'commandsMap'.
|
||||
Private Sub LoadSQLCommands(config2 As Map, DB As String)
|
||||
Dim newCommands As Map
|
||||
newCommands.Initialize
|
||||
@@ -181,48 +177,45 @@ Private Sub LoadSQLCommands(config2 As Map, DB As String)
|
||||
Main.commandsMap.Put(DB, commands)
|
||||
End Sub
|
||||
|
||||
' ** Delegación de estadísticas de C3P0 a HikariCP **
|
||||
' Delegation of statistics from C3P0 to HikariCP
|
||||
Public Sub GetPoolStats As Map
|
||||
Dim stats As Map
|
||||
stats.Initialize
|
||||
|
||||
If MyHikariPool.IsInitialized Then
|
||||
Try
|
||||
' 2. Llamamos al método delegado GetStats en el wrapper de HikariCP.
|
||||
' 2. Call the delegated GetStats method in the HikariCP wrapper.
|
||||
Dim hikariStats As Map = MyHikariPool.GetStats
|
||||
Return hikariStats
|
||||
Catch
|
||||
' Fallo en el método GetStats del wrapper.
|
||||
Dim ErrorMsg As String = $"RDCConnector.GetPoolStats: ERROR CRÍTICO al obtener estadísticas de HikariCP: ${LastException.Message}"$
|
||||
' Failure in the wrapper's GetStats method.
|
||||
Dim ErrorMsg As String = $"RDCConnector.GetPoolStats: CRITICAL ERROR getting stats from HikariCP: ${LastException.Message}"$
|
||||
Log(ErrorMsg)
|
||||
stats.Put("Error", LastException.Message)
|
||||
End Try
|
||||
Else
|
||||
stats.Put("Error", "Pool local MyHikariPool no inicializado.")
|
||||
stats.Put("Error", "Local pool MyHikariPool not initialized.")
|
||||
End If
|
||||
|
||||
Return stats
|
||||
End Sub
|
||||
|
||||
' *** NUEVA SUBRUTINA: Cierra el pool de conexiones de forma ordenada ***
|
||||
' Close the connection pool cleanly
|
||||
Public Sub Close
|
||||
If MyHikariPool.IsInitialized Then
|
||||
' Cierre limpio del pool subyacente.
|
||||
' Clean closure of the underlying pool.
|
||||
MyHikariPool.ClosePool
|
||||
Log($"RDCConnector.Close: Pool Hikari cerrado limpiamente para este conector."$)
|
||||
Log($"RDCConnector.Close: Hikari pool closed cleanly for this connector."$)
|
||||
End If
|
||||
' Ya NO delegamos el cierre al Manager.
|
||||
' ANTES: Main.ConnectionPoolManager1.ClosePoolByType(poolType) [15]
|
||||
' La línea de delegación a Main.ConnectionPoolManager1.ClosePoolByType(poolType) ha sido eliminada.
|
||||
End Sub
|
||||
|
||||
' --- SUBRUTINAS DE UTILIDAD PARA CARGA DE PROPIEDADES ---
|
||||
' --- UTILITY SUBROUTINES FOR LOADING PROPERTIES ---
|
||||
|
||||
' [2]
|
||||
Private Sub LoadDriverProperties(driverShortName As String, config_ As Map)
|
||||
driverProperties = ExtractProperties($"driver.${driverShortName.trim}."$, config_, Null, Null)
|
||||
End Sub
|
||||
|
||||
' [3]
|
||||
Private Sub ExtractProperties(prefix As String, input As Map, newPrefix As String, output As Map) As Map
|
||||
Dim properties As Map
|
||||
If output = Null Or output.IsInitialized = False Then
|
||||
@@ -232,7 +225,7 @@ Private Sub ExtractProperties(prefix As String, input As Map, newPrefix As Strin
|
||||
End If
|
||||
If newPrefix.EqualsIgnoreCase(Null) Then newPrefix = ""
|
||||
Dim prefixLength As Int = prefix.Length
|
||||
|
||||
|
||||
' Log($"Prefijo=${prefix}, ${newPrefix}"$)
|
||||
For Each k As String In input.Keys
|
||||
' Log(k)
|
||||
@@ -243,11 +236,11 @@ Private Sub ExtractProperties(prefix As String, input As Map, newPrefix As Strin
|
||||
properties.Put($"${newPrefix}${standardizedKey}"$, input.Get(k))
|
||||
End If
|
||||
Next
|
||||
|
||||
|
||||
Return properties
|
||||
End Sub
|
||||
|
||||
Private Sub LoadPoolProperties(poolType As String, config_ As Map)
|
||||
' Busca entradas como 'pool.hikari.<propiedad>' y las extrae.
|
||||
' Find entries like 'pool.hikari.<property>' and extract them.
|
||||
poolProperties = ExtractProperties($"pool.${poolType.ToLowerCase}."$, config_, Null, Null)
|
||||
End Sub
|
||||
End Sub
|
||||
|
||||
Reference in New Issue
Block a user