Feat: db reconnect
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ golias
|
||||
gralias
|
||||
store.json
|
||||
config.toml
|
||||
gralias.db
|
||||
|
BIN
gralias.db
BIN
gralias.db
Binary file not shown.
@ -75,6 +75,7 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
abortWithError(w, msg)
|
||||
return
|
||||
}
|
||||
var makeplayer bool
|
||||
roomID := r.PostFormValue("room_id")
|
||||
// make sure username does not exists
|
||||
cleanName := utils.RemoveSpacesFromStr(username)
|
||||
@ -90,7 +91,9 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
// userstate, err := loadState(cleanName)
|
||||
userstate, err := repo.PlayerGetByName(r.Context(), cleanName)
|
||||
if err != nil || userstate == nil {
|
||||
|
||||
userstate = models.InitPlayer(cleanName)
|
||||
makeplayer = true
|
||||
}
|
||||
fi := &models.FullInfo{
|
||||
State: userstate,
|
||||
@ -125,11 +128,13 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// save state to cache
|
||||
// if err := saveState(cleanName, userstate); err != nil {
|
||||
if err := repo.PlayerUpdate(r.Context(), userstate); err != nil {
|
||||
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||
log.Error("failed to save state", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
if makeplayer {
|
||||
if err := repo.PlayerAdd(r.Context(), userstate); err != nil {
|
||||
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||
log.Error("failed to save state", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil {
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
@ -17,7 +19,9 @@ type AllRepos interface {
|
||||
}
|
||||
|
||||
type RepoProvider struct {
|
||||
DB *sqlx.DB
|
||||
DB *sqlx.DB
|
||||
mu sync.RWMutex
|
||||
pathToDB string
|
||||
}
|
||||
|
||||
func NewRepoProvider(pathToDB string) *RepoProvider {
|
||||
@ -27,14 +31,65 @@ func NewRepoProvider(pathToDB string) *RepoProvider {
|
||||
os.Exit(1)
|
||||
}
|
||||
slog.Info("Successfully connected to database")
|
||||
return &RepoProvider{
|
||||
DB: db,
|
||||
rp := &RepoProvider{
|
||||
DB: db,
|
||||
pathToDB: pathToDB,
|
||||
}
|
||||
|
||||
go rp.pingLoop()
|
||||
|
||||
return rp
|
||||
}
|
||||
|
||||
func (rp *RepoProvider) pingLoop() {
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
if err := rp.pingDB(); err != nil {
|
||||
slog.Error("Database ping failed, attempting to reconnect...", "error", err)
|
||||
rp.reconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rp *RepoProvider) pingDB() error {
|
||||
rp.mu.RLock()
|
||||
defer rp.mu.RUnlock()
|
||||
if rp.DB == nil {
|
||||
return os.ErrClosed
|
||||
}
|
||||
return rp.DB.Ping()
|
||||
}
|
||||
|
||||
func (rp *RepoProvider) reconnect() {
|
||||
rp.mu.Lock()
|
||||
defer rp.mu.Unlock()
|
||||
|
||||
// Double-check if connection is still down
|
||||
if rp.DB != nil {
|
||||
if err := rp.DB.Ping(); err == nil {
|
||||
slog.Info("Database connection already re-established.")
|
||||
return
|
||||
}
|
||||
// if ping fails, we continue to reconnect
|
||||
rp.DB.Close() // close old connection
|
||||
}
|
||||
|
||||
slog.Info("Reconnecting to database...")
|
||||
db, err := sqlx.Connect("sqlite3", rp.pathToDB)
|
||||
if err != nil {
|
||||
slog.Error("Failed to reconnect to database", "error", err)
|
||||
rp.DB = nil // make sure DB is nil if connection failed
|
||||
return
|
||||
}
|
||||
|
||||
rp.DB = db
|
||||
slog.Info("Successfully reconnected to database")
|
||||
}
|
||||
|
||||
func getDB(ctx context.Context, db *sqlx.DB) sqlx.ExtContext {
|
||||
if tx, ok := ctx.Value("tx").(*sqlx.Tx);
|
||||
ok {
|
||||
if tx, ok := ctx.Value("tx").(*sqlx.Tx); ok {
|
||||
return tx
|
||||
}
|
||||
return db
|
||||
|
Reference in New Issue
Block a user