Documentation
¶
Overview ¶
Package lock provides implementations for cancellable and distributed locks.
Example ¶
service, err := New("local:")
if err != nil {
panic(err)
}
cfg := &SessionConfig{TTL: time.Second * 10}
id := "mylock"
counter := 0
niter := 1000
wg := &sync.WaitGroup{}
wg.Add(niter)
for i := 0; i < niter; i++ {
go func() {
session, err := service.NewSession(cfg)
if err != nil {
panic(err)
}
lock := session.NewLocker(id)
cancel, err := lock.Lock()
if err != nil {
panic(err)
}
select {
case <-cancel:
panic("lost lock")
default:
counter++
}
err = lock.Unlock()
if err != nil {
panic(err)
}
wg.Done()
}()
}
wg.Wait()
fmt.Println(counter)
Output: 1000
Index ¶
Examples ¶
Constants ¶
const ( // ServiceEtcd stands for service name. ServiceEtcd = "etcd" // DefaultDialTimeoutEtcd is the timeout for failing to establish a connection. DefaultDialTimeoutEtcd = 3 * time.Second )
const ServiceLocal = "local"
Variables ¶
var ( ErrUnsupportedService = errors.NewKind("unsupported service: %s") ErrInvalidConnectionString = errors.NewKind("invalid connection string: %s") ErrCanceled = errors.NewKind("context canceled") ErrAlreadyClosed = errors.NewKind("already closed") )
var Services map[string]func(string) (Service, error)
Services is a registry of all supported services by name. Map key is the service name, which will be looked up in URIs scheme.
Functions ¶
This section is empty.
Types ¶
type Locker ¶
type Locker interface {
// Context can be used to cancel the operation (e.g. with a timeout).
// If it succeeds, it returns a cancel channel. Otherwise, it returns an
// error. The cancel channel is closed whenever the lock is not held anymore.
// Note that the lock might be lost before calling to Unlock.
Lock() (<-chan struct{}, error)
// Unlock releases the lock. It might return an error if the lock could not
// be released cleanly. However, this error is merely informative and no
// action needs to be taken. Locking services must ensure that a lock that
// failed to be released cleanly expires at some point (e.g. after session
// TTL expires).
Unlock() error
}
Locker is the interface to a lock.
type Service ¶
type Service interface {
// NewSession creates a new locking session with the given configuration.
// An error is returned if the session cannot be created (e.g. invalid
// configuration, connection cannot be established to remote service).
NewSession(*SessionConfig) (Session, error)
// Close closes the service and releases any resources held by it.
// If it is called more than once, ErrAlreadyClosed is returned.
Close() error
}
Service is a locking service.
func NewEtcd ¶
NewEtcd creates a new locking service based on etcd given a connection string. The connection string has the following form:
etcd:<endpoints>[?<opt1>=<val1>&<opt2>=<val2>]
For example:
etcd:http//foo:8888,http://bar:9999?dial-timeout=2s&reject-old-cluster=true
Valid options are:
- auto-sync-interval (time duration)
- dial-timeout (time duration)
- dial-keep-alive-time (time duration)
- dial-keep-alive-timeout (time duration)
- username (string)
- password (string)
- reject-old-cluster (boolean)
For further information about each option, check the etcd godocs at: https://godoc.org/github.com/coreos/etcd/clientv3#Config
type Session ¶
type Session interface {
// NewService creates a NewService for the given id. Lockers returned for the
// same id on different sessions are mutually exclusive.
NewLocker(id string) Locker
// Close closes the session and releases any resources held by it.
// If it is called more than once, ErrAlreadyClosed is returned.
Close() error
// Done notifies the client when the session is finished.
Done() <-chan struct{}
}
Session is a locking session that can be reused to get multiple locks. Multiple actors should use different sessions.
type SessionConfig ¶
type SessionConfig struct {
// Timeout is the timeout when acquiring a lock. Calls to Lock() on a Locker
// in the session will fail if the lock cannot be acquired before timeout.
Timeout time.Duration
// TTL is the time-to-live of all locks in a session. A lock operation times
// out when the TTL expires. A lock is lost whenever it cannot be kept alive
// inside the TTL. For example, a lock in a distributed lock service maintains
// a keep alive heartbeat, once a heartbeat is not received for more than
// the specified TTL, it must be assumed that the lock is no longer held.
TTL time.Duration
}
SessionConfig holds configuration for a locking session.