Documentation
¶
Index ¶
- Variables
- func RouterFrom(store db.DB) (*replica.Router, error)
- func With(opts ...Option) db.Option
- type AfterConnectFunc
- type Config
- type Option
- func WithAfterConnect(fn AfterConnectFunc) Option
- func WithClassifier(c sqlclass.Classifier) Option
- func WithGateMaxWait(d time.Duration) Option
- func WithLogger(log *slog.Logger) Option
- func WithMaxReplicaLagBytes(n int64) Option
- func WithNoTrackerPolicy(p replica.NoTrackerPolicy) Option
- func WithReplicaFallback(policy replica.FallbackPolicy) Option
- func WithReplicaPollInterval(d time.Duration) Option
- func WithReplicaPollJitter(fraction float64) Option
- func WithReplicaPoolConfig(fn func(index int, cfg *pgxpool.Config)) Option
- func WithReplicaProbeTimeout(d time.Duration) Option
- func WithReplicaSampleStaleAfter(d time.Duration) Option
- func WithReplicaURI(uri ...string) Option
- func WithTxLookup(fn func(ctx context.Context) pgx.Tx) Option
- func WithWatermarkPolicy(policy replica.WatermarkPolicy) Option
- type PingConnectionError
- type Store
- type StoreError
- type Tracer
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidDSN indicates a connection string PostgreSQL cannot parse. ErrInvalidDSN = errors.New("invalid PostgreSQL DSN") // ErrClientConnection indicates a failure to reach the PostgreSQL server. ErrClientConnection = errors.New("failed to connect to PostgreSQL server") // ErrInvalidDatabase indicates the named database does not exist. ErrInvalidDatabase = errors.New("invalid database name") // ErrInvalidCredentials indicates the server rejected the credentials. ErrInvalidCredentials = errors.New("invalid PostgreSQL credentials") // ErrInvalidSchema indicates the named schema does not exist. ErrInvalidSchema = errors.New("invalid schema name") // ErrNotPostgresStore indicates the store is backed by another driver. ErrNotPostgresStore = errors.New("store is not backed by the postgres driver") )
Kinds of failure, for callers that want to branch rather than log.
Each is reachable with errors.Is on whatever Init returns: the driver classifies the underlying pgx error and wraps the matching sentinel alongside the cause, so both are found.
err := store.Init(ctx)
switch {
case errors.Is(err, postgres.ErrInvalidCredentials):
// the password is wrong, and retrying will not help
case errors.Is(err, postgres.ErrClientConnection):
// the server is unreachable, and retrying might
}
Functions ¶
func RouterFrom ¶
RouterFrom returns the read-replica router of a postgres store.
router, err := postgres.RouterFrom(store)
It reports ErrNotPostgresStore when another driver is in use, and replica.ErrRouterDisabled when no replicas were configured.
It deliberately does not return a nil router that quietly forwards everything to the primary. That shape is convenient right up to the day somebody spends an afternoon asking why the replica is idle.
func With ¶
With addresses this driver's options to db.New, so that client code passes them without naming the driver or giving up type safety:
store, err := db.New(ctx, log, tracer, metrics, cfg, postgres.With(postgres.WithAfterConnect(fn)), )
The options apply only when STORE_TYPE selects this driver.
Types ¶
type AfterConnectFunc ¶
AfterConnectFunc is a callback executed after each new connection is established.
type Option ¶
type Option func(*Store)
Option is a functional option for Store configuration.
Options are applied in Init, after the defaults and the configuration keys, so an option always wins over an environment variable.
func WithAfterConnect ¶
func WithAfterConnect(fn AfterConnectFunc) Option
WithAfterConnect sets a callback to be executed after each new connection. Useful for registering custom types (e.g., pgx-shopspring-decimal).
func WithClassifier ¶
func WithClassifier(c sqlclass.Classifier) Option
WithClassifier replaces the built-in statement classifier.
func WithGateMaxWait ¶
WithGateMaxWait bounds how long a caller waits inline for a replica to replay a required position. Zero disables waiting.
func WithLogger ¶
WithLogger gives the driver a logger. Without one, the replica poller stays silent about promotions and timeline switches, which are exactly the events you want to hear about.
The db.New constructor wires this from its own deps; set it only when building the store directly.
func WithMaxReplicaLagBytes ¶
WithMaxReplicaLagBytes is the staleness budget for reads that carry no watermark. Zero means unlimited.
It does not apply when a concrete watermark is being satisfied: comparing WAL positions is strictly stronger than comparing lag.
func WithNoTrackerPolicy ¶
func WithNoTrackerPolicy(p replica.NoTrackerPolicy) Option
WithNoTrackerPolicy decides where a read goes when its context carries neither a tracker nor an explicit strategy. Default replica.NoTrackerPrimary.
func WithReplicaFallback ¶
func WithReplicaFallback(policy replica.FallbackPolicy) Option
WithReplicaFallback sets what a read does when no replica qualifies. The default is replica.FallbackToPrimary.
Use replica.FallbackReject in tests, where a routing bug should be loud, or in a service that would rather shed read load than melt the primary. It never affects StrategyReplica, which never falls back either way.
func WithReplicaPollInterval ¶
WithReplicaPollInterval sets how often replica positions are refreshed. Zero disables the poller, which leaves every replica ineligible.
func WithReplicaPollJitter ¶
WithReplicaPollJitter spreads polls by the given fraction of the interval, so that a fleet of pods does not probe the same replica in lockstep. The value must be between zero and one; Init rejects an out-of-range configuration.
func WithReplicaPoolConfig ¶
WithReplicaPoolConfig adjusts each replica's pool before it is built — sizing, timeouts, application_name. It runs after the primary's settings have been copied over, with the replica's index.
func WithReplicaProbeTimeout ¶
WithReplicaProbeTimeout bounds a single health probe.
func WithReplicaSampleStaleAfter ¶
WithReplicaSampleStaleAfter sets the age past which a health sample is no longer trusted. A stale sample is indistinguishable from a hung replica.
func WithReplicaURI ¶
WithReplicaURI adds replica DSNs. Repeated calls append. With none, the router stays disabled and every statement runs on the primary.
One DSN must resolve to one standby. Pointing it at a load balancer in front of several standbys breaks the guarantee: the health probe describes one node and the read reaches another.
func WithTxLookup ¶
WithTxLookup lets the router honor a transaction the application manages itself. Wire it at the composition root:
postgres.With(postgres.WithTxLookup(uow.FromContext))
Without it the router cannot tell that a transaction is in flight, and will happily run the statement on a different connection — outside the transaction, without its locks, and able to deadlock against it. This is the single most dangerous way to use the router, so wire the hook.
func WithWatermarkPolicy ¶
func WithWatermarkPolicy(policy replica.WatermarkPolicy) Option
WithWatermarkPolicy sets when a committed transaction resolves its WAL position. WatermarkOnCommit costs one extra primary round trip per commit.
On-handoff capture is the default. In-request read-after-write needs only the taint, and a cross-boundary handoff is better served by calling Router.Watermark once, where the caller can see what it costs.
type PingConnectionError ¶
type PingConnectionError = db.PingConnectionError
The lifecycle error types are shared by every driver, so that a fix reaches all of them at once. Aliases rather than new types: existing callers keep working with *StoreError unchanged.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store implementation of db interface
func New ¶
func New(tracer trace.TracerProvider, metrics *metric.MeterProvider, cfg *config.Config, opts ...Option) *Store
New return new instance of Store
func (*Store) Close ¶
func (s *Store) Close()
Close releases the connection pools and stops the replica poller. It is idempotent, it waits for the poller goroutine to exit, and it is what context cancellation ends up calling.
Waiting matters: a poller that outlives its store shows up as a leaked goroutine in tests and as a slow climb in a service that rebuilds stores.
type StoreError ¶
type StoreError = db.StoreError
The lifecycle error types are shared by every driver, so that a fix reaches all of them at once. Aliases rather than new types: existing callers keep working with *StoreError unchanged.
type Tracer ¶
type Tracer struct {
trace.TracerProvider
}
Tracer is the tracer provider the store hands to otelpgx, which emits the query spans and their database attributes. A nil provider leaves the pool uninstrumented.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
middlewares
|
|
|
grpcmw
Package grpcmw carries the driver's read-your-writes guarantee across a gRPC hop.
|
Package grpcmw carries the driver's read-your-writes guarantee across a gRPC hop. |
|
httpmw
Package httpmw carries a read-your-writes guarantee across an HTTP request boundary.
|
Package httpmw carries a read-your-writes guarantee across an HTTP request boundary. |
|
metrics
Package metrics holds the OpenTelemetry instruments for read-replica routing.
|
Package metrics holds the OpenTelemetry instruments for read-replica routing. |
|
semconv
Package semconv holds the attribute keys and metric instruments of the postgres module as declared in the go-sdk semantic convention registry.
|
Package semconv holds the attribute keys and metric instruments of the postgres module as declared in the go-sdk semantic convention registry. |
|
sqlclass
Package sqlclass decides whether a SQL statement may run on a read replica.
|
Package sqlclass decides whether a SQL statement may run on a read replica. |
|
wal
Package wal models PostgreSQL Write-Ahead Log positions.
|
Package wal models PostgreSQL Write-Ahead Log positions. |