Documentation
¶
Overview ¶
Package db is nexus's driver-agnostic GORM manager. It mirrors the shape of oats_admin_backend/database.DBManager (Start/Stop/GetDB/IsConnected) and keeps the same failsafe-go retry + circuit-breaker behavior, but handles PostgreSQL, MySQL, and SQLite behind a single Config.Driver field.
Typical usage:
m, err := db.Open(db.Config{
Driver: db.SQLite,
Database: ":memory:",
})
if err != nil { return err }
m.Start() // background reconnect loop
defer m.Stop()
gdb := m.GetDB() // *gorm.DB — chain real queries
gdb.AutoMigrate(&User{})
gdb.Create(&User{Name: "A"})
Multi-DB? Wrap multiple Managers in a multi.Registry[*db.Manager] and call .Using(name).GetDB() from resolvers — see examples/graphapp.
Index ¶
- Variables
- type Config
- type Driver
- type EnvNames
- type Manager
- func (m *Manager) ConnectionString() string
- func (m *Manager) Driver() Driver
- func (m *Manager) GetCtx() context.Context
- func (m *Manager) GetDB() *gorm.DB
- func (m *Manager) IsConnected() bool
- func (m *Manager) NexusEnv() []manifest.EnvVar
- func (m *Manager) NexusServices() []manifest.ServiceNeed
- func (m *Manager) Ping(ctx context.Context) error
- func (m *Manager) Start()
- func (m *Manager) Stop()
- type Option
- type PoolConfig
- type ProvideOptions
Constants ¶
This section is empty.
Variables ¶
var DefaultEnvNames = EnvNames{
Host: "DB_HOSTNAME",
Port: "DB_PORT",
User: "DB_USERNAME",
Password: "DB_PASSWORD",
Database: "DB_NAME",
SSLMode: "DB_SSLMODE",
TimeZone: "DB_TIMEZONE",
}
DefaultEnvNames is the framework convention. Apps wiring db.Module without overrides get these names automatically.
Module is the fx wiring for an app that wants a single Manager with auto-manifest declarations. Compose with fx.Supply to feed the per-app ProvideOptions:
nexus.Run(cfg,
fx.Supply(db.ProvideOptions{
Driver: db.Postgres,
EnvNames: db.EnvNames{
User: "DB_USERNAME", Password: "PASSWORD",
Database: "DATABASE_NAME",
},
Defaults: db.Config{SSLMode: "disable", TimeZone: "UTC"},
}),
db.Module,
// ...other modules...
)
Apps that need multiple Managers don't use this Module — they wire each Manager via nexus.Provide(NewMyDBA, NewMyDBB, ...) and rely on the *App auto-walk in nexus.Provide to register both.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
Driver Driver
Host string
Port string
User string
Password string
Database string
SSLMode string // "disable" / "require" / ... — postgres only
TimeZone string // IANA TZ — postgres only
}
Config is the full connection spec. Host/Port/User/Password/SSLMode/TimeZone apply to postgres+mysql; Database is the db name for pg/mysql and the file path (":memory:" for in-memory) for sqlite.
func LoadConfig ¶ added in v0.22.2
LoadConfig builds a Config by reading os.Getenv against the effective name set. defaults supplies values for fields whose resolved env is empty — the runtime fallback chain. Driver is taken straight (env-derived drivers haven't proved useful in practice).
Side-effecting; called once from app constructors.
type Driver ¶
type Driver string
Driver picks the backing dialect. Each value has a corresponding Dialector that Config.Dialector() returns.
type EnvNames ¶ added in v0.22.2
type EnvNames struct {
Host, Port, User, Password, Database, SSLMode, TimeZone string
}
EnvNames maps each Config field that's normally env-driven to the env-var name that supplies its value. Same string serves two callers: Config.LoadEnv reads it (runtime); NexusEnv / NexusServices declare it (manifest). One signal, two consumers — no drift.
Zero-value fields fall back to DefaultEnvNames, so apps that follow the framework convention only override the names that differ.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns one *gorm.DB, reconnects in the background, and exposes the same method set as oats_admin_backend/database.DatabaseManager so it can drop in wherever that interface is expected.
func NewManager ¶
NewManager builds a Manager without connecting. Call Open or Start next.
func Open ¶
Open constructs a Manager and establishes the initial connection synchronously. Call Start() afterwards to enable the background reconnect + health-check loop.
func Provide ¶ added in v0.22.2
func Provide(lc fx.Lifecycle, opts ProvideOptions, logger *zap.Logger, reg manifest.Registrar) *Manager
Provide is the fx provider: builds a Manager from ProvideOptions, ties Start/Stop to the fx lifecycle, AND self-registers as a manifest.EnvProvider + ServiceDependencyProvider so the orchestration manifest reflects this DB's connection surface without app code calling DeclareEnv / DeclareService.
reg comes from the fx graph — *nexus.App satisfies the interface via its Declare* methods. Auto-supplied by fxEarlyOptions.
func (*Manager) ConnectionString ¶ added in v0.4.1
ConnectionString returns the DSN for this manager's configured driver (same string the Dialector is built from). Useful for diagnostics and for tooling that needs to reconnect outside GORM — migration CLIs, ad-hoc shell scripts, etc. Contains credentials in the Postgres/MySQL forms; don't log it in production.
func (*Manager) GetCtx ¶ added in v0.4.2
GetCtx returns the manager's internal context. It's canceled by Stop(), so goroutines that should die alongside the manager can bind to it:
go func() {
<-mgr.GetCtx().Done()
// manager has stopped; unwind our side here
}()
func (*Manager) IsConnected ¶
IsConnected returns true if a live connection is currently held.
func (*Manager) NexusEnv ¶ added in v0.22.2
NexusEnv lists the env vars this Manager reads, with required / secret / boundTo flags so the orchestration platform can render the deploy form correctly. Binding name is the manager's configured name (defaults to "main" — see NewManager / FromEnv).
func (*Manager) NexusServices ¶ added in v0.22.2
func (m *Manager) NexusServices() []manifest.ServiceNeed
NexusServices declares the backing database the orchestration platform should provision (or external-bind). Kind matches the Driver, so a postgres Manager declares a postgres need; a mysql Manager declares mysql.
type Option ¶
type Option func(*Manager)
Option tweaks a Manager at construction time.
func WithBindName ¶ added in v0.22.2
WithBindName names this Manager in the manifest. Defaults to "main"; multi-DB apps override per Manager so each shows up as a distinct slot in the orchestration canvas.
func WithEnvNames ¶ added in v0.22.2
WithEnvNames stamps the env-var names this Manager's Config came from onto the Manager so NexusEnv / NexusServices can declare them in the manifest. Empty fields fall back to DefaultEnvNames.
Use when the app reads from env-var names that don't follow the framework convention (e.g. oats reads PASSWORD instead of DB_PASSWORD). Apps that build their Config via LoadConfig pass the same EnvNames here.
func WithExecutor ¶
WithExecutor swaps in a custom failsafe executor. Useful if you want a different retry/circuit-breaker profile (the defaults match oats exactly).
func WithLogger ¶
WithLogger attaches a zap logger. Without one, Manager runs silently.
func WithPool ¶
func WithPool(p PoolConfig) Option
WithPool overrides the default connection-pool sizing.
type PoolConfig ¶
type PoolConfig struct {
MaxIdle int
MaxOpen int
ConnMaxLife time.Duration
ConnMaxIdle time.Duration
}
PoolConfig tunes the underlying *sql.DB pool. Defaults match oats's values for postgres/mysql; sqlite :memory: gets MaxOpen=1 to keep one in-memory database shared across goroutines.
type ProvideOptions ¶ added in v0.22.2
type ProvideOptions struct {
Driver Driver
// EnvNames overrides the framework defaults for env-var names.
// Empty fields inherit DefaultEnvNames so apps only override
// what differs.
EnvNames EnvNames
// Defaults supplies fallback values for fields whose env var
// resolves empty. SSLMode and TimeZone are the typical ones —
// most apps hard-code them rather than expose env knobs.
Defaults Config
// BindName names this Manager in the manifest. Defaults to
// "main". Multi-DB apps build multiple ProvideOptions with
// distinct names + sub-modules.
BindName string
}
ProvideOptions packages the inputs for the optional fx-graph constructor. Apps that want db.Module's auto-wiring populate this struct with their driver + per-app overrides; everything else falls back to defaults.
Why a struct (and not free-form options): fx wants concrete typed inputs in its graph. A single ProvideOptions value supplied via fx.Supply is the cleanest way to thread per-app config into a shared module without per-app fx wiring.