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.' and extract them. poolProperties = ExtractProperties($"pool.${poolType.ToLowerCase}."$, config_, Null, Null) End Sub