Documentation
¶
Overview ¶
Package db is the core's access to PostgreSQL (ADR-0003): a pool of the runtime role's connections, transactions with commit hooks, the check of the schema version, and the migrations, which only whitetower migrate applies, as the migration role (threat model, DC-3).
Index ¶
- Variables
- func Migrate(ctx context.Context, cfg config.Migration, logger *slog.Logger) error
- type DB
- func (db *DB) CheckSchema(ctx context.Context) error
- func (db *DB) Close()
- func (db *DB) Connect(ctx context.Context, purpose string, idle time.Duration) (*pgx.Conn, error)
- func (db *DB) Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error)
- func (db *DB) InTx(ctx context.Context, fn func(ctx context.Context, tx *Tx) error) error
- func (db *DB) Ping(ctx context.Context) error
- func (db *DB) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
- func (db *DB) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
- func (db *DB) Version(ctx context.Context) (int64, error)
- type Tx
- func (t *Tx) AfterCommit(fn func(ctx context.Context))
- func (t *Tx) BeforeCommit(fn func(ctx context.Context) error)
- func (t *Tx) CopyFrom(ctx context.Context, table pgx.Identifier, columns []string, ...) (int64, error)
- func (t *Tx) Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error)
- func (t *Tx) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
- func (t *Tx) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
- func (t *Tx) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults
Constants ¶
This section is empty.
Variables ¶
var ( // ErrSchemaBehind means that the database lacks migrations the binary // needs. ErrSchemaBehind = errors.New("the database schema is older than this binary: run whitetower migrate") // ErrSchemaAhead means that the database has migrations the binary does // not know. ErrSchemaAhead = errors.New("the database schema is newer than this binary") )
var ExpectedVersion = sync.OnceValue(func() int64 { entries, err := fs.ReadDir(migrations(), ".") if err != nil { panic(err) } var latest int64 for _, e := range entries { v, err := goose.NumericComponent(e.Name()) if err != nil { panic(fmt.Sprintf("migration %s: %v", e.Name(), err)) } latest = max(latest, v) } return latest })
ExpectedVersion returns the version of the newest migration in the binary: the schema it needs.
Functions ¶
func Migrate ¶
Migrate applies the pending migrations as the migration role. Concurrent runs, such as the init containers of several replicas, take turns on an advisory lock: one migrates while the others wait, up to 30 minutes, then find nothing left to do. It also lets the runtime role read the version table, through which the server checks the schema.
Types ¶
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB is a pool of the runtime role's connections. Its Exec, Query and QueryRow run outside any transaction; with them, DB serves the code that sqlc generates, as Tx does.
func Open ¶
Open prepares a pool of the runtime role's connections. It connects only when a connection is needed: a database that is down fails the readiness check, not the startup.
func (*DB) CheckSchema ¶
CheckSchema returns nil when the database's schema is the one the binary needs, and otherwise an error that wraps ErrSchemaBehind or ErrSchemaAhead. It is the readiness check "schema": the server waits for whitetower migrate, and refuses to start on a newer schema.
func (*DB) Connect ¶
Connect opens a session of the runtime role outside the pool, for work that holds a session: the notification listener and the locks of the background jobs. pg_stat_activity names it after the pool's connections and its purpose. The database ends the session once it has run no statement for idle, so that a replica cut off from the database neither holds locks nor holds back notifications for longer: the caller checks in more often. Closing the connection ends the session, and with it its locks and listens.
func (*DB) InTx ¶
InTx runs fn in a transaction of the runtime role, then the BeforeCommit hooks; then it commits and runs the AfterCommit hooks. An error from fn or from a BeforeCommit hook, or a panic, rolls everything back, and no AfterCommit hook runs. A transaction that loses a serialization conflict or a deadlock runs again, up to three times in all: fn must have no effect outside the transaction except through its hooks.
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx is a transaction that InTx runs. It runs statements but cannot end the transaction: InTx commits it or rolls it back.
func (*Tx) AfterCommit ¶
AfterCommit registers fn to run once the transaction has committed, for what must never happen for a change that rolled back and cannot take part in the transaction, such as work outside the database. fn gets a context that the caller's cancellation does not end, and handles its own failures: the change is already made. Notifications to the other replicas need no hook: notify.Bus sends them in the transaction itself.
func (*Tx) BeforeCommit ¶
BeforeCommit registers fn to run in the transaction, after the work and just before the commit; an error rolls the whole transaction back. It serves what must be done, or checked, once the transaction's work is complete.
func (*Tx) CopyFrom ¶
func (t *Tx) CopyFrom(ctx context.Context, table pgx.Identifier, columns []string, rows pgx.CopyFromSource) (int64, error)
CopyFrom inserts rows in bulk, in the transaction.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package dbtest gives integration tests a PostgreSQL database set up as in a deployment: a migration role that owns the schema, and a runtime role, member of whitetower_runtime, for the server.
|
Package dbtest gives integration tests a PostgreSQL database set up as in a deployment: a migration role that owns the schema, and a runtime role, member of whitetower_runtime, for the server. |