Documentation
¶
Overview ¶
Package lock defines the Locker interface and implements the locking logic.
Index ¶
- Constants
- Variables
- type Locker
- type SessionLocker
- type SessionLockerOption
- type TableLockerOption
- func WithTableHeartbeatInterval(interval time.Duration) TableLockerOption
- func WithTableLeaseDuration(duration time.Duration) TableLockerOption
- func WithTableLockID(lockID int64) TableLockerOption
- func WithTableLockTimeout(intervalDuration time.Duration, failureThreshold uint64) TableLockerOption
- func WithTableLogger(logger *slog.Logger) TableLockerOption
- func WithTableName(tableName string) TableLockerOption
- func WithTableRetryPolicy(retryPolicy func(error) bool) TableLockerOption
- func WithTableUnlockTimeout(intervalDuration time.Duration, failureThreshold uint64) TableLockerOption
Constants ¶
const ( // DefaultLockID is the id used to lock the database for migrations. It is a crc64 hash of the // string "goose". This is used to ensure that the lock is unique to goose. // // crc32.Checksum([]byte("goose"), crc32.MakeTable(crc32.IEEE)) DefaultLockID int64 = 4097083626 )
const (
// DefaultLockTableName is the default name of the lock table.
DefaultLockTableName = "goose_lock"
)
Variables ¶
var ( // ErrLockNotImplemented is returned when the database does not support locking. ErrLockNotImplemented = errors.New("lock not implemented") // ErrUnlockNotImplemented is returned when the database does not support unlocking. ErrUnlockNotImplemented = errors.New("unlock not implemented") )
Functions ¶
This section is empty.
Types ¶
type Locker ¶ added in v3.26.0
type Locker interface {
Lock(ctx context.Context, db *sql.DB) error
Unlock(ctx context.Context, db *sql.DB) error
}
Locker is the interface to lock and unlock the database.
Unlike SessionLocker, the Lock and Unlock methods are called on a *sql.DB and do not require the same connection to be used for both methods.
func NewPostgresTableLocker ¶ added in v3.26.0
func NewPostgresTableLocker(options ...TableLockerOption) (Locker, error)
NewPostgresTableLocker returns a Locker that uses PostgreSQL table-based locking. It manages a single lock row and keeps the lock alive automatically.
Default behavior:
- Lease (30s): How long the lock is valid if heartbeat stops
- Heartbeat (5s): How often the lock gets refreshed to keep it alive
- If the process dies, others can take the lock after lease expires
Defaults:
Table: "goose_lock" Lock ID: 4097083626 (crc64 of "goose") Lock retry: 5s intervals, 5min timeout Unlock retry: 2s intervals, 1min timeout
Lock and Unlock both retry on failure. Lock stays alive automatically until released. All defaults can be overridden with options.
type SessionLocker ¶
type SessionLocker interface {
SessionLock(ctx context.Context, conn *sql.Conn) error
SessionUnlock(ctx context.Context, conn *sql.Conn) error
}
SessionLocker is the interface to lock and unlock the database for the duration of a session. The session is defined as the duration of a single connection and both methods must be called on the same connection.
func NewPostgresSessionLocker ¶
func NewPostgresSessionLocker(opts ...SessionLockerOption) (SessionLocker, error)
NewPostgresSessionLocker returns a SessionLocker that utilizes PostgreSQL's exclusive session-level advisory lock mechanism.
This function creates a SessionLocker that can be used to acquire and release a lock for synchronization purposes. The lock acquisition is retried until it is successfully acquired or until the failure threshold is reached. The default lock duration is set to 5 minutes, and the default unlock duration is set to 1 minute.
If you have long running migrations, you may want to increase the lock duration.
See SessionLockerOption for options that can be used to configure the SessionLocker.
type SessionLockerOption ¶
type SessionLockerOption interface {
// contains filtered or unexported methods
}
SessionLockerOption is used to configure a SessionLocker.
func WithLockID ¶
func WithLockID(lockID int64) SessionLockerOption
WithLockID sets the lock ID to use when locking the database.
If WithLockID is not called, the DefaultLockID is used.
func WithLockTimeout ¶
func WithLockTimeout(period, failureThreshold uint64) SessionLockerOption
WithLockTimeout sets the max duration to wait for the lock to be acquired. The total duration will be the period times the failure threshold.
By default, the lock timeout is 300s (5min), where the lock is retried every 5 seconds (period) up to 60 times (failure threshold).
The minimum period is 1 second, and the minimum failure threshold is 1.
func WithUnlockTimeout ¶
func WithUnlockTimeout(period, failureThreshold uint64) SessionLockerOption
WithUnlockTimeout sets the max duration to wait for the lock to be released. The total duration will be the period times the failure threshold.
By default, the lock timeout is 60s, where the lock is retried every 2 seconds (period) up to 30 times (failure threshold).
The minimum period is 1 second, and the minimum failure threshold is 1.
type TableLockerOption ¶ added in v3.26.0
type TableLockerOption interface {
// contains filtered or unexported methods
}
TableLockerOption is used to configure a table-based locker.
func WithTableHeartbeatInterval ¶ added in v3.26.0
func WithTableHeartbeatInterval(interval time.Duration) TableLockerOption
WithTableHeartbeatInterval sets how often to send heartbeat updates to renew the lease. This should be significantly smaller than the lease duration.
func WithTableLeaseDuration ¶ added in v3.26.0
func WithTableLeaseDuration(duration time.Duration) TableLockerOption
WithTableLeaseDuration sets how long a lock lease lasts. The lock will expire after this duration if not renewed by heartbeat.
func WithTableLockID ¶ added in v3.26.0
func WithTableLockID(lockID int64) TableLockerOption
WithTableLockID sets the lock ID to use for this locker instance. Different lock IDs allow for multiple independent locks in the same table.
func WithTableLockTimeout ¶ added in v3.26.0
func WithTableLockTimeout(intervalDuration time.Duration, failureThreshold uint64) TableLockerOption
WithTableLockTimeout configures how long to retry acquiring a lock and how often to retry.
func WithTableLogger ¶ added in v3.26.0
func WithTableLogger(logger *slog.Logger) TableLockerOption
WithTableLogger sets an optional logger for lock operations. If not provided, lock operations will use a default logger that only logs errors to stderr.
func WithTableName ¶ added in v3.26.0
func WithTableName(tableName string) TableLockerOption
WithTableName sets the name of the lock table.
func WithTableRetryPolicy ¶ added in v3.26.0
func WithTableRetryPolicy(retryPolicy func(error) bool) TableLockerOption
WithTableRetryPolicy sets an optional callback to classify database errors during table lock operations.
The provided function is invoked whenever a database operation fails. This includes Lock(), Unlock(), and heartbeat/lease update operations.
If the function returns true, the operation is retried according to the configured retry/backoff policy.
If it returns false, the operation fails immediately, bypassing any retries.
This allows clients to implement custom logic for transient errors, driver-specific errors, or application-specific failure handling.
func WithTableUnlockTimeout ¶ added in v3.26.0
func WithTableUnlockTimeout(intervalDuration time.Duration, failureThreshold uint64) TableLockerOption
WithTableUnlockTimeout configures how long to retry releasing a lock and how often to retry.