session_locker_options.go

 1package lock
 2
 3import (
 4	"errors"
 5	"time"
 6)
 7
 8const (
 9	// DefaultLockID is the id used to lock the database for migrations. It is a crc64 hash of the
10	// string "goose". This is used to ensure that the lock is unique to goose.
11	//
12	// crc64.Checksum([]byte("goose"), crc64.MakeTable(crc64.ECMA))
13	DefaultLockID int64 = 5887940537704921958
14)
15
16// SessionLockerOption is used to configure a SessionLocker.
17type SessionLockerOption interface {
18	apply(*sessionLockerConfig) error
19}
20
21// WithLockID sets the lock ID to use when locking the database.
22//
23// If WithLockID is not called, the DefaultLockID is used.
24func WithLockID(lockID int64) SessionLockerOption {
25	return sessionLockerConfigFunc(func(c *sessionLockerConfig) error {
26		c.lockID = lockID
27		return nil
28	})
29}
30
31// WithLockTimeout sets the max duration to wait for the lock to be acquired. The total duration
32// will be the period times the failure threshold.
33//
34// By default, the lock timeout is 300s (5min), where the lock is retried every 5 seconds (period)
35// up to 60 times (failure threshold).
36//
37// The minimum period is 1 second, and the minimum failure threshold is 1.
38func WithLockTimeout(period, failureThreshold uint64) SessionLockerOption {
39	return sessionLockerConfigFunc(func(c *sessionLockerConfig) error {
40		if period < 1 {
41			return errors.New("period must be greater than 0, minimum is 1")
42		}
43		if failureThreshold < 1 {
44			return errors.New("failure threshold must be greater than 0, minimum is 1")
45		}
46		c.lockProbe = probe{
47			intervalDuration: time.Duration(period) * time.Second,
48			failureThreshold: failureThreshold,
49		}
50		return nil
51	})
52}
53
54// WithUnlockTimeout sets the max duration to wait for the lock to be released. The total duration
55// will be the period times the failure threshold.
56//
57// By default, the lock timeout is 60s, where the lock is retried every 2 seconds (period) up to 30
58// times (failure threshold).
59//
60// The minimum period is 1 second, and the minimum failure threshold is 1.
61func WithUnlockTimeout(period, failureThreshold uint64) SessionLockerOption {
62	return sessionLockerConfigFunc(func(c *sessionLockerConfig) error {
63		if period < 1 {
64			return errors.New("period must be greater than 0, minimum is 1")
65		}
66		if failureThreshold < 1 {
67			return errors.New("failure threshold must be greater than 0, minimum is 1")
68		}
69		c.unlockProbe = probe{
70			intervalDuration: time.Duration(period) * time.Second,
71			failureThreshold: failureThreshold,
72		}
73		return nil
74	})
75}
76
77type sessionLockerConfig struct {
78	lockID      int64
79	lockProbe   probe
80	unlockProbe probe
81}
82
83// probe is used to configure how often and how many times to retry a lock or unlock operation. The
84// total timeout will be the period times the failure threshold.
85type probe struct {
86	// How often (in seconds) to perform the probe.
87	intervalDuration time.Duration
88	// Number of times to retry the probe.
89	failureThreshold uint64
90}
91
92var _ SessionLockerOption = (sessionLockerConfigFunc)(nil)
93
94type sessionLockerConfigFunc func(*sessionLockerConfig) error
95
96func (f sessionLockerConfigFunc) apply(cfg *sessionLockerConfig) error {
97	return f(cfg)
98}