-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdlm.go
94 lines (74 loc) · 2.54 KB
/
dlm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Package dlm provides an abstraction library for multiple Distributed Lock Manager backends.
package dlm
import (
"crypto/rand"
"encoding/base64"
"fmt"
"time"
)
const (
// DefaultTTL is the TTL of the lock after wich it will be automatically released.
DefaultTTL = 15 * time.Second
// DefaultWaitTime is how long will we wait to acquire a lock.
DefaultWaitTime = 15 * time.Second
// DefaultRetryTime is how long will we wait after a failed lock adquisition
// before attempting to acquire the lock again.
DefaultRetryTime = 5 * time.Second
)
var (
// ErrLockHeld is returned if we attempt to acquire a lock that is already held.
ErrLockHeld = fmt.Errorf("lock already held")
// ErrLockNotHeld is returned if we attempt to release a lock that is not held.
ErrLockNotHeld = fmt.Errorf("lock not held")
// ErrCannotLock is returned when it's not possible to acquire the lock before
// the configured wait time ends.
ErrCannotLock = fmt.Errorf("timeout while trying to acquire lock")
)
// DLM describes a Distributed Lock Manager.
type DLM interface {
// NewLock creates a lock for the given key. The returned lock is not held
// and must be acquired with a call to .Lock.
NewLock(string, *LockOptions) (Locker, error)
}
// Options parameterizes a DLM.
type Options struct {
Namespace string // Optional namespace prefixed to each lock key.
}
// LockOptions parameterizes a lock.
type LockOptions struct {
TTL time.Duration // Optional, defaults to DefaultTTL
WaitTime time.Duration // Optional, defaults to DefaultWaitTime
RetryTime time.Duration // Optional, defaults to DefaultRetryTime
}
// WithDefaults returns the options with all default values set.
func (lo *LockOptions) WithDefaults() *LockOptions {
if lo.TTL == 0 {
lo.TTL = DefaultTTL
}
if lo.WaitTime == 0 {
lo.WaitTime = DefaultWaitTime
}
if lo.RetryTime == 0 {
lo.RetryTime = DefaultRetryTime
}
return lo
}
// Locker describes a lock that can be locked or unlocked.
type Locker interface {
// Key returns the key to be locked.
Key() string
// Namespace returns the the prefix to be added to the key. If there is not a namespace,
// it returns the empty string.
Namespace() string
// Lock acquires the lock. It fails with error if the lock is already held.
Lock() error
// Unlock releases the lock. It fails with error if the lock is not currently held.
Unlock() error
}
func randstr(size int) (string, error) {
buffer := make([]byte, size)
if _, err := rand.Read(buffer); err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(buffer), nil
}