package database import ( "os" "time" "log/slog" "github.com/jmoiron/sqlx" _ "github.com/mattn/go-sqlite3" "github.com/pkg/errors" ) var ( log = slog.New(slog.NewJSONHandler(os.Stdout, nil)) dbDriver = "sqlite3" ) type DB struct { Conn *sqlx.DB URI string } func (d *DB) CloseAll() error { for _, conn := range []*sqlx.DB{d.Conn} { if err := closeConn(conn); err != nil { return err } } return nil } func closeConn(conn *sqlx.DB) error { return conn.Close() } func Init(DBURI string) (*DB, error) { var result DB var err error result.Conn, err = openDBConnection(DBURI, dbDriver) if err != nil { return nil, err } result.URI = DBURI if err := testConnection(result.Conn); err != nil { return nil, err } return &result, nil } func openDBConnection(dbURI, driver string) (*sqlx.DB, error) { conn, err := sqlx.Open(driver, dbURI) if err != nil { return nil, err } return conn, nil } func testConnection(conn *sqlx.DB) error { err := conn.Ping() if err != nil { return errors.Wrap(err, "can't ping database") } return nil } func (d *DB) PingRoutine(interval time.Duration) { ticker := time.NewTicker(interval) done := make(chan bool) for { select { case <-done: return case t := <-ticker.C: if err := testConnection(d.Conn); err != nil { log.Error("failed to ping postrges db", "error", err, "ping_at", t) // reconnect if err := closeConn(d.Conn); err != nil { log.Error("failed to close db connection", "error", err, "ping_at", t) } d.Conn, err = openDBConnection(d.URI, dbDriver) if err != nil { log.Error("failed to reconnect", "error", err, "ping_at", t) } } } } }