Vai al contenuto

WDO MySQL - Configurazione

Ci sono tre modi per avviare il pool MySQL. Quello consigliato è il dichiarativo da config.json.

Metodo 1 - Dichiarativo (consigliato)

Aggiungi la sezione databases in www/config.json:

{
  "databases": {
    "mysql": {
      "driver":     "mysql",
      "host":       "127.0.0.1",
      "user":       "harbour",
      "pwd":        "hb1234",
      "db":         "employees",
      "port":       3306,
      "pool_size":         5,
      "timeout_ms":        5000,
      "ping":              true,
      "read_timeout_s":    30,
      "connect_timeout_s": 10,
      "berror":            "WDO_DefaultErrorHandler"
    }
  }
}

In app.prg con hixstyle non hai bisogno di altro: Start() chiama automaticamente HIX_InitPoolsFromConfig() e HIX_EndPoolsFromConfig().

In app senza hixstyle:

PROCEDURE Main()
   LOCAL oSrv := THixServer():New()
   HIX_ConfigAppLoad( "www/config.json" )
   HIX_InitPoolsFromConfig()   // interrompe se qualche pool fallisce (default)
   oSrv:Start()
   IF oSrv:hThread != NIL
      hb_threadJoin( oSrv:hThread )
   ENDIF
   HIX_EndPoolsFromConfig()
RETURN

Pool multipli

Puoi dichiarare più database con chiavi distinte:

{
  "databases": {
    "mysql":     { "driver": "mysql",   "host": "127.0.0.1", ... },
    "analytics": { "driver": "mariadb", "host": "10.0.0.42", ... }
  }
}

Negli handler: WDO_Get("mysql") e WDO_Get("analytics") coesistono nello stesso processo.

Campi disponibili

Campo Default Descrizione
driver (obbligatorio) "mysql" o "mariadb" (case-insensitive)
host "localhost" IP o hostname del server
user "" Utente di autenticazione
pwd "" Password
db "" Database di default
port 3306 Porta TCP
pool_size 5 Numero di connessioni all'avvio
timeout_ms 5000 Tempo massimo di attesa in WDO_Get() (0 = infinito)
ping true Ping prima di consegnare ogni slot; riconnette se è inattivo
read_timeout_s 30 Timeout di lettura/scrittura del socket MySQL in secondi (0 = senza timeout). Limita il blocco in recv() quando un thread figlio del dispatcher supera exec_timeout_ms; senza di esso la connessione diventa zombie e lo slot non torna mai al pool
connect_timeout_s 10 Timeout della fase di connessione al server in secondi (0 = senza timeout). Evita che l'avvio del pool rimanga bloccato se il server MySQL non risponde
debug false Se un pool ha "debug": true, HIX_Dbg() globale viene attivato: dbg.log registra Acquire/Release del pool e ogni HIX_Dbg() strumentato nei controller. dbg.log viene svuotato all'avvio. Solo in sviluppo — ha costo di I/O.
berror - Nome della funzione Harbour per gestire gli errori del pool
dll - Percorso esplicito alla DLL (override della risoluzione automatica)

Relazione con exec_timeout_ms

read_timeout_s deve essere maggiore della query legittima più lenta e in linea con exec_timeout_ms del dispatcher (in hix.json). Se aumenti exec_timeout_ms, aumenta anche read_timeout_s: se una query dura più del socket read timeout, MySQL restituirà errore prima che la query termini.

berror di default

"berror": "WDO_DefaultErrorHandler" è già incluso nella lib: registra l'errore con le() e restituisce 500 se c'è una richiesta attiva. Sufficiente per la maggior parte dei progetti.

Metodo 2 - Programmatico hash

WDO_InitPoolMySqlEx( "mysql", { ;
   "host"       => hb_GetEnv( "DB_HOST" ), ;
   "user"       => hb_GetEnv( "DB_USER" ), ;
   "pwd"        => hb_GetEnv( "DB_PWD" ),  ;
   "db"         => "employees",            ;
   "pool_size"  => 10,                     ;
   "timeout_ms" => 5000,                   ;
   "ping"       => .T.,                    ;
   "berror"     => "WDO_DefaultErrorHandler" ;
} )

Utile quando le credenziali vengono lette da variabili d'ambiente o segreti.

Metodo 3 - Posizionale (legacy)

WDO_InitPoolMySql( "localhost", "harbour", "hb1234", "employees", 3306, ;
                    5,     /* pool_size   */ ;
                    5000,  /* timeout_ms  */ ;
                    .T.,   /* ping        */ ;
                    {|oErr, oConn| WdoErrorHandler( oErr, oConn ) } )

Registra il pool sotto la chiave fissa "MYSQL". Compatibile con codice precedente alla v2.3.01.


DLL - driver MySQL vs MariaDB

Il driver richiede la libreria client del protocollo MySQL:

"driver" DLL Windows SO Linux
"mysql" libmysql64.dll libmysqlclient.so
"mariadb" libmariadb64.dll libmariadb.so

Precedenza di risoluzione della DLL

Il driver cerca la libreria in questo ordine (priorità maggiore prima):

  1. Campo "dll" in config.json - percorso assoluto esplicito per pool.
  2. Variabile d'ambiente WDO_LIB_MYSQL - percorso assoluto al file.
  3. Variabile d'ambiente WDO_PATH_MYSQL - directory; il driver aggiunge il nome canonico.
  4. Directory dell'eseguibile (hb_DirBase()).
  5. PATH di sistema - nome canonico senza percorso.

Diagnostica

oSrv:AddRouteGet( "dbinfo", "/dbinfo", {||
   LOCAL oConn := WDO_Get( "mysql" )
   IF oConn == NIL ; RETURN USendError( 503, "pool unavailable" ) ; ENDIF
   USendJson( { ;
      "dll_source" => oConn:DllSource(), ;
      "dll_path"   => oConn:DllPath(),   ;
      "server"     => oConn:mysql_get_server_info() ;
   } )
   oConn:Close()
} )

DllSource() restituisce "override", "WDO_LIB_MYSQL", "WDO_PATH_MYSQL", "exedir" o "default".

Se la DLL non viene trovata

Il pool fallisce all'avvio e scrive in console:

==> Error: Cannot load MySQL DLL

Con HIX_InitPoolsFromConfig(.T.) il server si interrompe. Con .F. continua, ma WDO_Get("mysql") restituirà NIL e gli handler risponderanno con 503.


Gestore degli errori personalizzato

Se hai bisogno di logica custom (alert Slack, metriche, ecc.), definisci una funzione pubblica:

FUNCTION WdoErrorHandler( oErr, oConn )

   HB_SYMBOL_UNUSED( oConn )

   le( "[WDO] " + oErr:description + " @ " + oErr:operation )

   IF HIX_GetRequest() != NIL
      USendError( 500, "DB error: " + oErr:description )
   ENDIF

RETURN NIL

E referenziala nel JSON:

"berror": "WdoErrorHandler"