Files
panel/controller/internal/db/db.go
T
dbledeez a00bd620a1 Panel — public source drop (v0.9.0)
Self-hostable game-server control panel: controller + agent + 26 game
modules. One-line install (prebuilt release, no Go required):

  curl -fsSL https://git.pdxtechs.com/dbledeez/panel/raw/branch/main/install.sh | sudo bash

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:17:39 -07:00

59 lines
1.4 KiB
Go

// Package db owns the Controller's durable state in Postgres. It exposes
// a small typed surface (UpsertAgent, InsertInstance, ListInstances, …)
// built on pgx/v5 with a connection pool. Migrations are embedded so the
// binary is self-contained.
package db
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
// DB wraps a pgx pool with our typed query methods.
type DB struct {
pool *pgxpool.Pool
}
// Open connects to Postgres using dsn, pings once to fail fast on bad
// credentials or unreachable server, and runs any pending migrations.
func Open(ctx context.Context, dsn string) (*DB, error) {
cfg, err := pgxpool.ParseConfig(dsn)
if err != nil {
return nil, fmt.Errorf("parse db dsn: %w", err)
}
cfg.MaxConns = 10
cfg.MaxConnLifetime = 30 * time.Minute
pool, err := pgxpool.NewWithConfig(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("new pool: %w", err)
}
pingCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if err := pool.Ping(pingCtx); err != nil {
pool.Close()
return nil, fmt.Errorf("ping db: %w", err)
}
if err := Migrate(ctx, pool); err != nil {
pool.Close()
return nil, fmt.Errorf("migrate: %w", err)
}
return &DB{pool: pool}, nil
}
// Close releases pool resources.
func (db *DB) Close() {
if db != nil && db.pool != nil {
db.pool.Close()
}
}
// Pool exposes the underlying pool for tests / advanced callers.
func (db *DB) Pool() *pgxpool.Pool { return db.pool }