Almost all request will need the database connection, either because they will perform queries or because they need to check if the user is logged in, for instance, so it should be acquired as far above as possible to avoid acquiring multiple connections. This is specially true since i have to pass the cookie to the database to switch role and set request.user.email and request.user.cookie config variables. I do not want to do that many times per request.
78 lines
1.6 KiB
Go
78 lines
1.6 KiB
Go
/*
|
|
* SPDX-FileCopyrightText: 2023 jordi fita mas <jfita@peritasoft.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
package database
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/jackc/pgx/v4"
|
|
"github.com/jackc/pgx/v4/pgxpool"
|
|
)
|
|
|
|
func New(ctx context.Context, connString string) (*DB, error) {
|
|
config, err := pgxpool.ParseConfig(connString)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
config.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
|
|
if _, err := conn.Exec(ctx, "set search_path to camper, public"); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
config.AfterRelease = func(conn *pgx.Conn) bool {
|
|
if _, err := conn.Exec(context.Background(), "reset role"); err != nil {
|
|
log.Printf("ERROR - failed to reset role: %v", err)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
pool, err := pgxpool.ConnectConfig(ctx, config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &DB{pool}, nil
|
|
}
|
|
|
|
type DB struct {
|
|
*pgxpool.Pool
|
|
}
|
|
|
|
func (db *DB) Acquire(ctx context.Context) (*Conn, error) {
|
|
conn, err := db.Pool.Acquire(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Conn{conn}, nil
|
|
}
|
|
|
|
func (db *DB) MustAcquire(ctx context.Context, cookie string) *Conn {
|
|
conn, err := db.Acquire(ctx)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if _, err = conn.Exec(ctx, "select set_cookie($1)", cookie); err != nil {
|
|
panic(false)
|
|
}
|
|
return conn
|
|
}
|
|
|
|
type Conn struct {
|
|
*pgxpool.Conn
|
|
}
|
|
|
|
func (c *Conn) MustGetText(ctx context.Context, sql string, args ...interface{}) string {
|
|
var result string
|
|
if err := c.QueryRow(ctx, sql, args...).Scan(&result); err != nil {
|
|
panic(err)
|
|
}
|
|
return result
|
|
}
|