Documentation
¶
Overview ¶
Package database owns the engine's sharded SQL connections: it opens and migrates every shard, routes by 1-based shard index, fans an operation out over all shards, and closes them. It is DB-lifecycle-complete (open → migrate → size → fan-out → close) and speaks only in resolved connection-pool sizes - the sizing *policy* (how many connections a worker count implies) stays with the caller, which hands ShardSet the two computed integers via Config / SetMax*Conns.
Index ¶
- func TestID(name string) string
- type Config
- type ShardConfig
- type ShardSet
- func (s *ShardSet) Close()
- func (s *ShardSet) Has(n int) bool
- func (s *ShardSet) Indices() []int
- func (s *ShardSet) NumShards() int
- func (s *ShardSet) OnEach(ctx context.Context, ...) error
- func (s *ShardSet) Open(ctx context.Context, cfg Config) error
- func (s *ShardSet) SetMaxIdleConns(n int)
- func (s *ShardSet) SetMaxOpenConns(n int)
- func (s *ShardSet) Shard(n int) (*sequel.DB, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func TestID ¶ added in v0.10.0
TestID hashes a caller-chosen test name into the key Config.TestID takes: bounded to 16 hex chars so the database name sequel derives from it stays inside the strictest SQL identifier limit (Postgres 63 / MySQL 64) whatever the name's length, and salted with this process's run nonce so concurrent runs of the same package do not fight over one database.
The same name yields the same id for the life of the process and a different one in the next, which is the property every caller wants: shared within a test, isolated between runs.
Types ¶
type Config ¶
type Config struct {
// Shards maps each shard index to its configuration. Indices must be >= 1 but need not be
// contiguous (index 0 is the "no shard / all shards" sentinel). A nil/empty map defaults to a
// single shard 1 with an empty DSN and a minimal pool.
Shards map[int]ShardConfig
// TestID, when non-empty, wraps each shard via sequel.CreateTestingDatabase into an isolated, auto-dropped
// database keyed on (driver, baseDSN, TestID) - the resolved per-shard DSNs already distinguish the shards.
TestID string
// TestConnCap, when > 0 (and TestID != ""), caps every shard's pool at this many connections and
// reserves TestConnCap*numShards from a per-driver global budget for the Open->Close lifetime, so many
// parallel test engines against one server stay under its max_connections (see testbudget.go). Ignored
// entirely in production (TestID == "").
TestConnCap int
Logger *slog.Logger
TracerProvider trace.TracerProvider // nil → otel.GetTracerProvider()
MeterProvider metric.MeterProvider // nil → otel.GetMeterProvider()
}
Config is the full open-time configuration of a ShardSet.
type ShardConfig ¶ added in v0.10.0
type ShardConfig struct {
// DSN is the sequel data source name, used EXACTLY as given: it is never formatted or substituted, so
// a percent-encoded credential survives it intact. In test mode (Config.TestID set) it is a template -
// an empty DSN falls back to SEQUEL_TESTING_DSN and then the SQLite in-memory default, and a "%d" is
// replaced with the shard index, which is what makes each shard's test database distinct.
DSN string
MaxIdleConns int
MaxOpenConns int
}
ShardConfig is one shard's open-time configuration: its DSN and its resolved pool sizes. The connection-sizing formula is the caller's concern; this package applies the two integers verbatim.
type ShardSet ¶
type ShardSet struct {
// contains filtered or unexported fields
}
ShardSet is the engine's set of open, migrated database shards. The zero value is a usable, empty set. The shard indices are fixed for the set's life (established at Open), so a caller may size per-shard state from Indices()/NumShards() and key it by the shard arg without racing a concurrent change. Indices are sparse: they must be unique and >= 1 but need not be contiguous.
func (*ShardSet) Close ¶
func (s *ShardSet) Close()
Close closes all shard connections and empties the set.
func (*ShardSet) Indices ¶ added in v0.10.0
Indices returns the open shard indices in ascending order.
func (*ShardSet) OnEach ¶
func (s *ShardSet) OnEach(ctx context.Context, op func(ctx context.Context, db *sequel.DB, shard int) error) error
OnEach fans op out over every shard concurrently using an errgroup-style wait. Every shard is always attempted; if several fail, the error of the LOWEST shard index is the one returned (deterministic, not whichever failed first - the ops run concurrently, so "first" would be a race).
The returned error carries a "shard" property naming the failing shard. Without it an operator sees the reaper or the refiller fail with a bare driver error and no clue WHICH database is unhealthy - and this package's whole contract is that a persistent outage degrades loudly. The property is a NAMED pair deliberately: an unnamed int in this errors package is read as an HTTP status code, so passing the index bare would silently set the error's status.
func (*ShardSet) Open ¶
Open opens and migrates every shard, applying cfg's pool sizes and telemetry. On any shard failure it closes the shards already opened this attempt (so a partial failure leaks no connections and leaves the set empty for a clean retry) and returns the error. Not safe to call concurrently with itself; call once at startup.
func (*ShardSet) SetMaxIdleConns ¶
SetMaxIdleConns applies the given idle-connection pool size to every open shard, clamped to the test-mode cap so the engine's derived sizing can never grow a pool past the reserved budget.
func (*ShardSet) SetMaxOpenConns ¶
SetMaxOpenConns applies the given open-connection pool ceiling to every open shard, clamped to the test-mode cap (see SetMaxIdleConns).