hakobox/database/database.go
2025-04-21 17:59:57 -03:00

86 lines
2 KiB
Go

package database
import (
"context"
"database/sql"
"embed"
"fmt"
"log"
"os"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/joho/godotenv"
"github.com/pressly/goose/v3"
)
var (
instance *sql.DB
errNoRowsAffected = fmt.Errorf("no rows affected")
//go:embed migrations/*.sql
embedMigrations embed.FS
)
func New() *sql.DB {
// Evita criar mais de um banco
if instance != nil {
return instance
}
// Carrega as variáveis de ambiente definadas no arquivo .env na raiz do projeto.
err := godotenv.Load()
if err != nil {
panic(err)
}
// Para rodar os testes desse pacote, É necessário que haja um symlink de um .env nesta
// pasta (database/) apontando para o .env no topo do projeto, já que 'go test' usa o
// diretório raiz do pacote (./database) para executar os testes enquanto 'go run' usa o diretório
// raiz do projeto.
// variáveis ambientais de .env são carregadas para o ambiente do nosso processo, basta
// usar a forma padrão para pegar os valores dessas variáveis.
var (
user = os.Getenv("PG_USER")
pass = os.Getenv("PG_PASS")
dbName = os.Getenv("PG_DB")
hostAddr = os.Getenv("PG_ADDR")
)
connectionString := fmt.Sprintf("postgresql://%s:%s@%s:5432/%s", user, pass, hostAddr, dbName)
db, err := sql.Open("pgx", connectionString)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
panic(err)
}
// Verifica se a conexão foi um sucesso
if err := db.Ping(); err != nil {
panic(err)
}
goose.SetBaseFS(embedMigrations)
if err := goose.SetDialect("postgres"); err != nil {
panic(err)
}
// Aplica todas as migrações disponíveis
if err := goose.Up(db, "migrations"); err != nil {
panic(err)
}
instance = db
log.Println("Nova instância do banco de dados foi criada.")
return instance
}
func MustBeginTx() *sql.Tx {
if instance == nil {
panic(fmt.Errorf("Banco de dados não foi inicializado. Não foi possível criar nova transação."))
}
tx, err := instance.BeginTx(context.Background(), nil)
if err != nil {
panic(err)
}
return tx
}