Files
ziggie 325f83c179 sqldb+lncfg: consolidate SQLite default constants
Move the SQLite default constants (max connections, busy timeout) to
sqldb/config.go as the single source of truth and export them. Remove
the duplicate definitions from lncfg/db.go and reference the sqldb
constants instead.
2026-02-11 13:15:56 +01:00

108 lines
4.3 KiB
Go

package sqldb
import (
"fmt"
"net/url"
"time"
)
const (
// defaultMaxConns is the number of permitted active and idle
// connections. We want to limit this so it isn't unlimited. We use the
// same value for the number of idle connections as, this can speed up
// queries given a new connection doesn't need to be established each
// time.
defaultMaxConns = 25
// connIdleLifetime is the amount of time a connection can be idle.
connIdleLifetime = 5 * time.Minute
)
// SqliteConfig holds all the config arguments needed to interact with our
// sqlite DB.
//
//nolint:ll
type SqliteConfig struct {
Timeout time.Duration `long:"timeout" description:"The time after which a database query should be timed out."`
BusyTimeout time.Duration `long:"busytimeout" description:"The maximum amount of time to wait for a database connection to become available for a query."`
MaxConnections int `long:"maxconnections" description:"The maximum number of open connections to the database. Set to zero for unlimited."`
PragmaOptions []string `long:"pragmaoptions" description:"A list of pragma options to set on a database connection. For example, 'auto_vacuum=incremental'. Note that the flag must be specified multiple times if multiple options are to be set."`
SkipMigrations bool `long:"skipmigrations" description:"Skip applying migrations on startup."`
QueryConfig `group:"query" namespace:"query"`
}
const (
// DefaultSqliteMaxConns is the default number of maximum open
// connections for SQLite. SQLite only supports a single writer, so a
// low default reduces contention on the busy_timeout and limits
// resource usage, especially on mobile.
DefaultSqliteMaxConns = 2
// DefaultSqliteBusyTimeout is the default busy_timeout value used
// when no BusyTimeout is configured.
DefaultSqliteBusyTimeout = 5 * time.Second
)
// busyTimeoutMs returns the busy_timeout value in milliseconds. If
// BusyTimeout is not set, it returns the default value.
func (s *SqliteConfig) busyTimeoutMs() int64 {
if s.BusyTimeout > 0 {
return s.BusyTimeout.Milliseconds()
}
return DefaultSqliteBusyTimeout.Milliseconds()
}
// MaxConns returns the effective maximum number of open connections. If
// MaxConnections is not set, it returns a default of 2. This low default is
// chosen because SQLite only supports a single writer, which helps reduce
// contention and resource usage.
func (s *SqliteConfig) MaxConns() int {
if s.MaxConnections > 0 {
return s.MaxConnections
}
return DefaultSqliteMaxConns
}
// Validate checks that the SqliteConfig values are valid.
func (p *SqliteConfig) Validate() error {
if err := p.QueryConfig.Validate(true); err != nil {
return fmt.Errorf("invalid query config: %w", err)
}
return nil
}
// PostgresConfig holds the postgres database configuration.
//
//nolint:ll
type PostgresConfig struct {
Dsn string `long:"dsn" description:"Database connection string."`
Timeout time.Duration `long:"timeout" description:"Database connection timeout. Set to zero to disable."`
MaxConnections int `long:"maxconnections" description:"The maximum number of open connections to the database. Set to zero for unlimited."`
SkipMigrations bool `long:"skipmigrations" description:"Skip applying migrations on startup."`
ChannelDBWithGlobalLock bool `long:"channeldb-with-global-lock" description:"Use a global lock for channeldb access. This ensures only a single writer at a time but reduces concurrency. This is a temporary workaround until the revocation log is migrated to a native sql schema."`
WalletDBWithGlobalLock bool `long:"walletdb-with-global-lock" description:"Use a global lock for wallet database access. This ensures only a single writer at a time but reduces concurrency. This is a temporary workaround until the wallet subsystem is upgraded to a native sql schema."`
QueryConfig `group:"query" namespace:"query"`
}
// Validate checks that the PostgresConfig values are valid.
func (p *PostgresConfig) Validate() error {
if p.Dsn == "" {
return fmt.Errorf("DSN is required")
}
// Parse the DSN as a URL.
_, err := url.Parse(p.Dsn)
if err != nil {
return fmt.Errorf("invalid DSN: %w", err)
}
if err := p.QueryConfig.Validate(false); err != nil {
return fmt.Errorf("invalid query config: %w", err)
}
return nil
}