Documentation
¶
Index ¶
- Constants
- Variables
- func GetContext(ctx context.Context) (bun.IDB, error)
- func InTx(ctx context.Context) bool
- func NewContext(ctx context.Context, config Config) (context.Context, error)
- func NewContextSchema(ctx context.Context, config Config, schema string, create bool) (context.Context, error)
- func NewContextTest(ctx context.Context, config Config) (context.Context, string, error)
- func Ping(ctx context.Context, client *bun.DB) error
- func RunDBTest(t *testing.T, config Config, migrations fs.FS, callback TransactionalTestFunc)
- func RunIsolatedTransactionalTest(t *testing.T, config Config, migrations fs.FS, callback TransactionalTestFunc)
- func RunMigrationRoundtripTest(t *testing.T, config Config, migrations fs.FS, opts *RoundtripOptions)
- func RunMigrations(ctx context.Context, db *bun.DB, migrations fs.FS) error
- func RunMigrationsContext(ctx context.Context, migrations fs.FS) error
- func RunTransactionalTest(t *testing.T, config Config, callback TransactionalTestFunc)
- func SchemaSnapshot(ctx context.Context, db bun.IDB, schema string) (string, error)
- func SnapshotDelta(want, got string) []string
- func TransferContext(baseCtx, destCtx context.Context) context.Context
- func WithTx(ctx context.Context, tx bun.IDB) context.Context
- func WithinTx(ctx context.Context, opts *sql.TxOptions, ...) error
- type Config
- type ContextKey
- type PassthroughTx
- type RoundtripOptions
- type TransactionalTestFunc
- type Transactor
Constants ¶
const ( // PingTimeout bounds how long Ping keeps retrying before giving up. PingTimeout = 10 * time.Second // PingRetryInterval is the wait between failed ping attempts, keeping Ping // from tight-looping reconnects on an unreachable database. PingRetryInterval = 100 * time.Millisecond )
const NameLen = 31
NameLen caps the length of a generated schema or database name, keeping it within PostgreSQL's 63-byte identifier limit with room for prefixes.
Variables ¶
var ErrNoDbInContext = errors.New("context does not contain a bun.DB")
ErrNoDbInContext is returned by RunMigrationsContext when the context carries a bun.IDB that is not a full *bun.DB, which migrations require. ErrNoIDBInContext covers the case of no connection at all.
var ErrNoIDBInContext = errors.New("context does not contain a bun.IDB")
ErrNoIDBInContext is returned by GetContext when the context carries no bun.IDB, meaning it was never seeded by NewContext or one of its variants. ErrNoDbInContext covers the stricter case where a connection is present but is not a full *bun.DB.
var ErrUnsupportedSchemaObject = errors.New("schema holds an object class the census cannot render")
ErrUnsupportedSchemaObject reports a schema object the census cannot safely compare. Such objects fail instead of being silently omitted.
Functions ¶
func GetContext ¶
GetContext returns the bun.IDB stored in ctx by NewContext or one of its variants, or ErrNoIDBInContext when none is present.
func InTx ¶ added in v0.23.0
InTx reports whether ctx carries an open transaction. It reports false when ctx carries the connection pool, and false when it carries no database at all.
Work that must not hold a pooled connection — any call to an external service — guards itself with this.
It reports true under RunTransactionalTest, whose PassthroughTx is not a *bun.DB. A test covering an outbound call must therefore use RunDBTest, which puts a real pool on the context.
func NewContext ¶
NewContext derives a context carrying a connection to the primary database, for later retrieval with GetContext.
func NewContextSchema ¶
func NewContextSchema(ctx context.Context, config Config, schema string, create bool) (context.Context, error)
NewContextSchema derives a context carrying a connection scoped to the named schema, creating the schema first when create is true.
func NewContextTest ¶
NewContextTest derives a context bound to a fresh, randomly named schema created through config, isolating the test from others sharing the database. It returns the schema name so the caller can drop it once done.
func Ping ¶
Ping a database connection until it succeeds or the timeout is reached. Honors ctx cancellation both for the PingContext call and for the wait between retries.
func RunDBTest ¶ added in v0.22.0
RunDBTest runs callback against its own freshly created PostgreSQL database, cloned from a migrated template via `CREATE DATABASE … TEMPLATE`. Every call is physically isolated, so the caller may mark the test and its sub-tests t.Parallel() even when they reuse the same fixture keys.
The cost model is "migrate once, clone many": the migration set is applied a single time into a template database whose name is a hash of the migrations, and each test gets a fast file-level copy of it. The per-test database is dropped (WITH FORCE) in t.Cleanup; the template is left in place and reused across runs as long as the migrations are unchanged.
config must expose Options() []pgdriver.Option (postgrespresets.Default does). callback receives a context carrying a real *bun.DB for the per-test database, retrievable with GetContext.
func RunIsolatedTransactionalTest ¶
func RunIsolatedTransactionalTest(t *testing.T, config Config, migrations fs.FS, callback TransactionalTestFunc)
RunIsolatedTransactionalTest runs callback in a throwaway schema, which admits operations a transaction cannot host concurrently, such as refreshing a materialized view.
The schema lives in the existing database, so its extensions remain available. Each call reruns the whole migration set, which makes RunTransactionalTest the cheaper default.
func RunMigrationRoundtripTest ¶ added in v0.30.0
func RunMigrationRoundtripTest(t *testing.T, config Config, migrations fs.FS, opts *RoundtripOptions)
RunMigrationRoundtripTest proves that every down migration exactly reverses its up.
It snapshots each up, verifies each down against the preceding snapshot, then re-applies the full set. Fixtures run between steps. Snapshots bind each schema to its exact migration prefix.
config must expose Options() []pgdriver.Option, as postgrespresets.Default does.
func RunMigrations ¶
RunMigrations runs all the migrations found in the provided filesystem.
func RunMigrationsContext ¶
RunMigrationsContext runs all the migrations found in the provided filesystem, using the database connection from the context.
func RunTransactionalTest ¶
func RunTransactionalTest(t *testing.T, config Config, callback TransactionalTestFunc)
RunTransactionalTest runs callback inside a transaction that is rolled back on cleanup. The context carries a PassthroughTx, which discards sub-transactions so concurrent calls sharing the connection cannot deadlock.
func SchemaSnapshot ¶ added in v0.30.0
SchemaSnapshot renders supported schema objects as canonical, sorted, one-line records. PostgreSQL renders definitions, so statement order and DDL spelling do not affect the result.
It includes database-scoped extensions and schemas, reads no row data, and returns ErrUnsupportedSchemaObject rather than omitting an unsupported class.
func SnapshotDelta ¶ added in v0.30.0
SnapshotDelta returns sorted per-object differences between want and got. Records are compared as a set.
func TransferContext ¶
TransferContext transfers the current postgres context into another. If the source context is not a postgres context, this is a no-op.
func WithTx ¶ added in v0.23.0
WithTx derives a context carrying tx, so GetContext resolves that transaction.
WithinTx applies this for you and is what callers normally want. WithTx is exported for the cases that own the transaction lifecycle themselves — a test harness wrapping a whole suite, or a caller bridging a transaction it opened through some other API.
func WithinTx ¶ added in v0.23.0
func WithinTx(ctx context.Context, opts *sql.TxOptions, callback func(ctx context.Context) error) error
WithinTx runs callback inside a transaction opened on the connection carried by ctx, and installs that transaction on the context callback receives, so every call made with it takes part in the transaction.
The callback takes no transaction argument: the context it receives is the only database handle reachable inside it, so no call can escape unnoticed.
A nested call joins the transaction already in progress, so one unit of work has one outcome and a rollback anywhere discards all of it. A nested call never reaches opts: an operation depending on a specific isolation level must be the outermost transaction.
Types ¶
type Config ¶
type Config interface {
// DB returns a connection to the primary database, opening it on first call
// and reusing it thereafter.
DB(ctx context.Context) (*bun.DB, error)
// DBSchema returns a connection scoped to the named schema, creating the
// schema first when create is true. An empty schema name yields the primary
// connection.
DBSchema(ctx context.Context, schema string, create bool) (*bun.DB, error)
}
Config supplies pooled bun database connections to the rest of the package. A Config owns the driver options and the connection lifecycle; the context, migration, and test helpers all obtain their handles through it. postgrespresets.Default is the standard implementation.
type ContextKey ¶
type ContextKey struct{}
ContextKey is the context value key under which the package stores the active bun.IDB connection.
type PassthroughTx ¶
PassthroughTx extends bun.Tx so that a nested transaction call resolves to the same transaction.
PostgreSQL has no nested transactions, so bun opens a savepoint instead. A savepoint belongs to its parent's query stream and cannot serve parallel callers, which breaks a test suite that wraps the whole application in one transaction and then calls a method from several goroutines.
func NewPassthroughTx ¶
func NewPassthroughTx(tx bun.Tx) *PassthroughTx
NewPassthroughTx wraps tx so that nested transaction calls resolve to tx itself.
func (*PassthroughTx) Commit ¶
func (tx *PassthroughTx) Commit() error
func (*PassthroughTx) Rollback ¶
func (tx *PassthroughTx) Rollback() error
type RoundtripOptions ¶ added in v0.30.0
type RoundtripOptions struct {
// Fixtures holds optional `<timestamp>_<name>.sql` files, applied after the named migration.
Fixtures fs.FS
// Snapshots holds one history-bound schema snapshot per migration. GOLIB_UPDATE_SNAPSHOTS
// rewrites them.
Snapshots string
}
RoundtripOptions configures RunMigrationRoundtripTest. Its zero value is valid.
type TransactionalTestFunc ¶
TransactionalTestFunc is the body of a database-backed test, run with a context carrying the connection isolated for that test.
type Transactor ¶ added in v0.23.0
type Transactor struct {
// contains filtered or unexported fields
}
A Transactor is the PostgreSQL implementation of github.com/a-novel-kit/golib/transaction.Transactor.
func NewTransactor ¶ added in v0.23.0
func NewTransactor(opts *sql.TxOptions) *Transactor
NewTransactor returns a Transactor opening its transactions with opts. A nil opts leaves the database defaults in place, which is read-committed isolation.
func (*Transactor) WithinTx ¶ added in v0.23.0
func (transactor *Transactor) WithinTx(ctx context.Context, fn func(ctx context.Context) error) error
WithinTx satisfies github.com/a-novel-kit/golib/transaction.Transactor.