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.
247 lines
8.9 KiB
QBasic
247 lines
8.9 KiB
QBasic
B4J=true
|
|
Group=Default Group
|
|
ModulesStructureVersion=1
|
|
Type=Class
|
|
Version=4.19
|
|
@EndOfDesignText@
|
|
' Class module: RDCConnector
|
|
' This class manages the connection pool for a specific database.
|
|
' Uses ConnectionPoolManager and delegates to HikariCP.
|
|
|
|
Sub Class_Globals
|
|
' --- 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 ' 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
|
|
|
|
' Initialization subroutine for a specific database connector.
|
|
Public Sub Initialize(DB As String)
|
|
' 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
|
|
|
|
' Load the configuration from the corresponding .properties file.
|
|
config = LoadConfigMap(dbKey) ' Ensure it's loaded into the class variable
|
|
|
|
' Read the parameter tolerance configuration
|
|
Dim toleranceSetting As Int = config.GetDefault("parameterTolerance", 0).As(Int)
|
|
IsParameterToleranceEnabled = (toleranceSetting = 1)
|
|
|
|
If IsParameterToleranceEnabled Then
|
|
Log($"RDCConnector.Initialize for ${dbKey}: Extra parameter tolerance ENABLED."$)
|
|
Else
|
|
Log($"RDCConnector.Initialize for ${dbKey}: Extra parameter tolerance DISABLED (strict mode)."$)
|
|
End If
|
|
|
|
' 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" ' Force Hikari
|
|
|
|
' --- Size precedence logic (HIKARI) ---
|
|
Dim maxSizeKey As String = $"pool.${poolType.ToLowerCase}.maximumpoolsize"$
|
|
Dim poolSizeString As String
|
|
Dim poolSize As Int
|
|
|
|
' Attempt to read the specific value (pool.hikari.maximumpoolsize).
|
|
If config.ContainsKey(maxSizeKey) Then
|
|
poolSizeString = config.Get(maxSizeKey)
|
|
poolSize = poolSizeString.As(Int)
|
|
Else
|
|
' If not defined, use the recommended Hikari default (10).
|
|
poolSize = 10
|
|
End If
|
|
|
|
If poolSize < 1 Then poolSize = 10 ' Keep it sensible
|
|
Log($"RDCConnector: Using MaximumPoolSize for ${poolType} calculated: ${poolSize}"$)
|
|
|
|
' 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)
|
|
|
|
' Load and filter ONLY the Pool properties (e.g., those starting with 'pool.hikari.')
|
|
LoadPoolProperties(poolType, config)
|
|
|
|
' Apply STABILITY properties (Pool Properties)
|
|
If poolProperties.Size > 0 Then
|
|
' Direct application to the local pool.
|
|
CallSub2(MyHikariPool, "SetProperties", poolProperties)
|
|
End If
|
|
|
|
' Load specific Driver properties (e.g., Statement Caching)
|
|
If config.ContainsKey("DriverShortName") Then
|
|
LoadDriverProperties(config.Get("DriverShortName"), config)
|
|
End If
|
|
|
|
' Apply PERFORMANCE properties (Driver Properties)
|
|
If driverProperties.Size > 0 Then
|
|
' Direct application to the local pool.
|
|
CallSub2(MyHikariPool, "SetDriverProperties", driverProperties)
|
|
Log($"RDCConnector.Initialize for ${DB}: {driverProperties.Size} Driver properties applied to HikariCP."$)
|
|
End If
|
|
|
|
' 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
|
|
|
|
' Load static configuration into the global cache
|
|
Dim dbKeyToStore As String = DB
|
|
If dbKeyToStore = "" Then dbKeyToStore = "DB1"
|
|
|
|
' 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
|
|
' 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)
|
|
|
|
' 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
|
|
|
|
' 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
|
|
|
|
' Load the configuration map
|
|
Private Sub LoadConfigMap(DB As String) As Map
|
|
Private DBX As String = ""
|
|
If DB <> "" Then DBX = "." & DB
|
|
Log($"RDCConnector.LoadConfigMap: Reading config${DBX}.properties"$)
|
|
Return File.ReadMap("./", "config" & DBX & ".properties")
|
|
End Sub
|
|
|
|
' 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: *** 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
|
|
|
|
' Get a functional SQL connection from the connection pool.
|
|
Public Sub GetConnection(DB As String) As SQL
|
|
' 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: 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
|
|
End Sub
|
|
|
|
' 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
|
|
For Each k As String In config2.Keys
|
|
If k.StartsWith("sql.") Then
|
|
newCommands.Put(k, config2.Get(k))
|
|
End If
|
|
Next
|
|
commands = newCommands
|
|
Main.commandsMap.Put(DB, commands)
|
|
End Sub
|
|
|
|
' Delegation of statistics from C3P0 to HikariCP
|
|
Public Sub GetPoolStats As Map
|
|
Dim stats As Map
|
|
stats.Initialize
|
|
|
|
If MyHikariPool.IsInitialized Then
|
|
Try
|
|
' 2. Call the delegated GetStats method in the HikariCP wrapper.
|
|
Dim hikariStats As Map = MyHikariPool.GetStats
|
|
Return hikariStats
|
|
Catch
|
|
' 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", "Local pool MyHikariPool not initialized.")
|
|
End If
|
|
|
|
Return stats
|
|
End Sub
|
|
|
|
' Close the connection pool cleanly
|
|
Public Sub Close
|
|
If MyHikariPool.IsInitialized Then
|
|
' Clean closure of the underlying pool.
|
|
MyHikariPool.ClosePool
|
|
Log($"RDCConnector.Close: Hikari pool closed cleanly for this connector."$)
|
|
End If
|
|
' La línea de delegación a Main.ConnectionPoolManager1.ClosePoolByType(poolType) ha sido eliminada.
|
|
End Sub
|
|
|
|
' --- UTILITY SUBROUTINES FOR LOADING PROPERTIES ---
|
|
|
|
Private Sub LoadDriverProperties(driverShortName As String, config_ As Map)
|
|
driverProperties = ExtractProperties($"driver.${driverShortName.trim}."$, config_, Null, Null)
|
|
End Sub
|
|
|
|
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
|
|
properties.Initialize
|
|
Else
|
|
properties = output
|
|
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)
|
|
If k.ToLowerCase.StartsWith(prefix) Then
|
|
' Log($"found ${prefix}"$)
|
|
Dim standardizedKey As String = k.SubString(prefixLength).ToLowerCase
|
|
' Log("Ponemos: " & $"${newPrefix}${k.SubString(prefixLength)}, ${input.Get(k)}"$)
|
|
properties.Put($"${newPrefix}${standardizedKey}"$, input.Get(k))
|
|
End If
|
|
Next
|
|
|
|
Return properties
|
|
End Sub
|
|
|
|
Private Sub LoadPoolProperties(poolType As String, config_ As Map)
|
|
' Find entries like 'pool.hikari.<property>' and extract them.
|
|
poolProperties = ExtractProperties($"pool.${poolType.ToLowerCase}."$, config_, Null, Null)
|
|
End Sub
|