Feat: db reconnect

This commit is contained in:
Grail Finder
2025-07-03 10:39:14 +03:00
parent e02554b181
commit c82439d43a
4 changed files with 71 additions and 10 deletions

View File

@ -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