feat: add a NOOP db interface to make internal.Q() safe

This commit is contained in:
Adriano Caloiaro 2025-02-13 14:11:25 -07:00
parent 3039016280
commit 45dc9ecf22
No known key found for this signature in database
GPG key ID: C2BC56DE73CE3F75
2 changed files with 36 additions and 3 deletions

View file

@ -117,3 +117,15 @@ func TestCopyForm(t *testing.T) {
return
}
}
func TestNoopWhenPoolUnavailable(t *testing.T) {
ctx := context.Background()
_, err := internal.Q(ctx, internal.DBArgs{
URL: "INVALID URL",
DisableSSL: true,
Schema: "frm_test",
}).GetForm(ctx, internal.GetFormParams{})
if err != internal.ErrNoopDatabase {
t.Error(fmt.Errorf("expected: '%s' but got: '%s'", internal.ErrNoopDatabase, err))
}
}

View file

@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"log/slog"
"math/rand"
"strings"
@ -14,9 +13,32 @@ import (
_ "github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool"
)
var (
ErrNoopDatabase = errors.New("frm had a problem getting a database connection")
)
type MockRow struct{}
type NoopDBTX struct{}
func (m *MockRow) Scan(dest ...any) (err error) {
return ErrNoopDatabase
}
func (n *NoopDBTX) Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) {
return pgconn.CommandTag{}, ErrNoopDatabase
}
func (n *NoopDBTX) Query(context.Context, string, ...interface{}) (pgx.Rows, error) {
return nil, ErrNoopDatabase
}
func (n *NoopDBTX) QueryRow(context.Context, string, ...interface{}) pgx.Row {
return &MockRow{}
}
type contextKey string
const (
@ -96,8 +118,7 @@ func getPool(ctx context.Context, args DBArgs) (p *pgxpool.Pool, err error) {
func Q(ctx context.Context, args DBArgs) *Queries {
p, err := getPool(ctx, args)
if err != nil {
slog.Error("database pool unavailable", "error", err)
return nil // TODO return a no-op DBTX to avoid NPEs
return New(&NoopDBTX{})
}
return New(p)
}