Fixing database interaction + adding stored routine calls
This commit is contained in:
parent
b03e2d2af1
commit
c40d035f30
@ -51,6 +51,7 @@ func Init(router *mux.Router) {
|
||||
|
||||
func apiRoot(w http.ResponseWriter, r *http.Request) {
|
||||
tStart := time.Now()
|
||||
database.ExecuteStoredRoutine("test")
|
||||
fmt.Fprintf(w, "API ROOT")
|
||||
profiler.Add(profiler_API_PROCESS_REQUEST, time.Duration(time.Since(tStart).Microseconds()))
|
||||
}
|
||||
@ -66,7 +67,6 @@ func apiAuth(w http.ResponseWriter, r *http.Request) {
|
||||
func apiAuthLogin(w http.ResponseWriter, r *http.Request) {
|
||||
tStart := time.Now()
|
||||
fmt.Fprintf(w, "API Auth Login")
|
||||
database.Ping()
|
||||
profiler.Add(profiler_API_PROCESS_REQUEST, time.Duration(time.Since(tStart).Microseconds()))
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@ -14,12 +15,18 @@ import (
|
||||
const (
|
||||
profiler_DATABASE_CONNECT string = "Database Connect"
|
||||
profiler_DATABASE_QUERY string = "Database Query"
|
||||
profiler_DATABASE_PING string = "Database Ping"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
const (
|
||||
database_ROUTINE_TYPE_PROCEDURE uint8 = 1
|
||||
database_ROUTINE_TYPE_FUNCTION uint8 = 2
|
||||
)
|
||||
|
||||
var dbPath string
|
||||
var dbConfig config.Database
|
||||
var isInit bool
|
||||
var storedRoutines map[string]uint8
|
||||
var db *sql.DB
|
||||
|
||||
func Init() {
|
||||
if isInit {
|
||||
@ -27,47 +34,21 @@ func Init() {
|
||||
}
|
||||
|
||||
dbConfig = config.GetConfig().Database
|
||||
dbPath = fmt.Sprintf("%s:%s@(%s:%d)/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database)
|
||||
|
||||
profiler.Register(profiler_DATABASE_CONNECT, 20, "µs")
|
||||
profiler.Register(profiler_DATABASE_CONNECT, 200, "µs")
|
||||
profiler.Register(profiler_DATABASE_QUERY, 4000, "µs")
|
||||
profiler.Register(profiler_DATABASE_PING, 20, "µs")
|
||||
|
||||
isInit = true
|
||||
|
||||
Connect()
|
||||
|
||||
var query string = `SHOW GRANTS;`
|
||||
var rows *sql.Rows = executeQuery(query)
|
||||
if rows != nil {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var res string
|
||||
rows.Scan(&res)
|
||||
fmt.Println(res)
|
||||
}
|
||||
fetchStoredRoutines()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Terminate() {
|
||||
isInit = false
|
||||
if db != nil {
|
||||
db.Close()
|
||||
db = nil
|
||||
}
|
||||
}
|
||||
|
||||
func Connect() {
|
||||
func connect() {
|
||||
if !isInit {
|
||||
return
|
||||
}
|
||||
|
||||
if db != nil {
|
||||
db.Close()
|
||||
}
|
||||
|
||||
var err error
|
||||
var dbPath string = fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database)
|
||||
log.Printf("Connecting to database %s at %s:%d as %s\n", dbConfig.Database, dbConfig.Host, dbConfig.Port, dbConfig.User)
|
||||
|
||||
tStart := time.Now()
|
||||
@ -77,82 +58,145 @@ func Connect() {
|
||||
break
|
||||
}
|
||||
log.Printf("Error while connecting the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
||||
if i+1 == dbConfig.RetriesOnError {
|
||||
break
|
||||
}
|
||||
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
||||
}
|
||||
profiler.Add(profiler_DATABASE_CONNECT, time.Duration(time.Since(tStart).Microseconds()))
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln("Cannot connect to database !")
|
||||
}
|
||||
|
||||
Ping()
|
||||
db.SetConnMaxLifetime(time.Minute * 1)
|
||||
db.SetMaxOpenConns(100)
|
||||
db.SetMaxIdleConns(100)
|
||||
|
||||
ping()
|
||||
|
||||
profiler.Add(profiler_DATABASE_CONNECT, time.Duration(time.Since(tStart).Microseconds()))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func Disconnect() {
|
||||
func ExecuteStoredRoutine(name string, args ...any) {
|
||||
if !isInit {
|
||||
return
|
||||
}
|
||||
if storedRoutines == nil {
|
||||
fetchStoredRoutines()
|
||||
}
|
||||
|
||||
if db == nil {
|
||||
var exist bool
|
||||
var routineType uint8
|
||||
routineType, exist = storedRoutines[name]
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
|
||||
db.Close()
|
||||
}
|
||||
|
||||
func Ping() {
|
||||
if !isInit {
|
||||
return
|
||||
}
|
||||
|
||||
if db == nil {
|
||||
return
|
||||
switch routineType {
|
||||
case database_ROUTINE_TYPE_PROCEDURE:
|
||||
callStoredProcedure(name, args...)
|
||||
case database_ROUTINE_TYPE_FUNCTION:
|
||||
callStoredFunction(name, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func ping() {
|
||||
var err error
|
||||
tStart := time.Now()
|
||||
for i := range dbConfig.RetriesOnError {
|
||||
err = db.Ping()
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
log.Printf("Error while pinging the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
||||
if i+1 == dbConfig.RetriesOnError {
|
||||
break
|
||||
}
|
||||
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
||||
}
|
||||
profiler.Add(profiler_DATABASE_PING, time.Duration(time.Since(tStart).Microseconds()))
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln("Cannot ping the database !")
|
||||
}
|
||||
}
|
||||
|
||||
func executeQuery(query string) *sql.Rows {
|
||||
func executeQuery(query string, args ...any) *sql.Rows {
|
||||
if !isInit {
|
||||
return nil
|
||||
}
|
||||
|
||||
if db == nil {
|
||||
return nil
|
||||
connect()
|
||||
}
|
||||
|
||||
Ping()
|
||||
|
||||
var err error
|
||||
var rows *sql.Rows
|
||||
tStart := time.Now()
|
||||
for i := range dbConfig.RetriesOnError {
|
||||
rows, err = db.Query(query)
|
||||
rows, err = db.Query(query, args...)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
log.Printf("Error while querying the database [%d/%d] : %s\n", i+1, dbConfig.RetriesOnError, err)
|
||||
if i+1 == dbConfig.RetriesOnError {
|
||||
break
|
||||
}
|
||||
time.Sleep((time.Duration)(dbConfig.TimeBetweenRetriesMs) * time.Millisecond)
|
||||
ping()
|
||||
}
|
||||
profiler.Add(profiler_DATABASE_QUERY, time.Duration(time.Since(tStart).Microseconds()))
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln("Cannot query the database !")
|
||||
log.Printf("Cannot query the database ! (Query : %s) with args ", query)
|
||||
log.Fatalln(args...)
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func fetchStoredRoutines() {
|
||||
storedRoutines = nil
|
||||
var query string = fmt.Sprintf("SELECT ROUTINE_NAME, ROUTINE_TYPE FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA=\"%s\";", dbConfig.Database)
|
||||
var rows *sql.Rows = executeQuery(query)
|
||||
if rows != nil {
|
||||
storedRoutines = make(map[string]uint8, 0)
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var resName, resType string
|
||||
rows.Scan(&resName, &resType)
|
||||
switch resType {
|
||||
case "PROCEDURE":
|
||||
storedRoutines[resName] = database_ROUTINE_TYPE_PROCEDURE
|
||||
case "FUNCTION":
|
||||
storedRoutines[resName] = database_ROUTINE_TYPE_FUNCTION
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println(storedRoutines)
|
||||
}
|
||||
|
||||
func callStoredProcedure(name string, args ...any) {
|
||||
var query string
|
||||
if len(args) == 0 {
|
||||
query = fmt.Sprintf("CALL %s()", name)
|
||||
} else if len(args) == 1 {
|
||||
query = fmt.Sprintf("CALL %s(?)", name)
|
||||
} else {
|
||||
query = strings.Repeat(", ?", len(args)-1)
|
||||
query = fmt.Sprintf("CALL %s(?%s)", name, query)
|
||||
}
|
||||
|
||||
var rows *sql.Rows = executeQuery(query, args...)
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var res string
|
||||
rows.Scan(&res)
|
||||
log.Println(res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func callStoredFunction(name string, args ...any) {
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user