Documentation
¶
Overview ¶
Package locker is a distributed lock service built on top of etcd. https://github.com/coreos/etcd
Locker gives you a way of creating and maintaining locks across a network, useful for synchronising access to resources when multiple machines are involved.
A simple example is a name server. A service would lock its hostname record and set the value to its IP address:
client.Lock("www.example.com", "10.1.1.1", nil, nil)
Other clients wanting to resolve the address could call
client.Get("www.example.com")
and would recieve the IP address: 10.1.1.1.
This gets a bit more interesting when clients start watching the records and are notified of changes when they occur.
valueChanges := make(chan string) go client.Watch("www.example.com", valueChanges, nil) select { case newIp := <-valueChanges: redirectRequestsToNewIp(newIp) }
Index ¶
- Constants
- type Client
- func (c Client) Get(name string) (string, error)
- func (c Client) Inspect(name string) Report
- func (c Client) Lock(name, value string, quit <-chan bool) Report
- func (c Client) Unlock(name string, quit chan<- bool) error
- func (c Client) Watch(name string, valueChanges chan<- string, quit <-chan bool) error
- type EtcdStore
- type LockDenied
- type LockNotFound
- type Report
- type Store
Constants ¶
const ( Fail string = "fail" Success = "success" )
const DefaultValue = "ok"
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct { // Store is what locker uses to persist locks. Store Store // contains filtered or unexported fields }
Client is the main locker type. Use it to manage your locks. A locker Client has a Store which it uses to persist the locks.
func New ¶
New creates a default locker client using Etcd as a store. It requires you provide an etcd.Client, this is so locker doesn't make any dumb assumptions about how your Etcd cluster is configured.
client := locker.New(etcdclient)
func (Client) Get ¶
Get returns the value of a lock. LockNotFound will be returned if a lock with the name isn't held.
func (Client) Lock ¶
Lock will create a lock for a key and set its value. If the owned channel is provided a bool will be pushed whenever our ownership of the lock changes. Pushing true into the quit channel will stop the locker from refreshing the lock and let it expire if we own it.
owned := make(chan bool) go client.Lock("my-service", "http://10.0.0.1:9292", owned, nil) for { select { case v := <-owned: fmt.Printf("Lock ownership changed: %t\n", v) } }
Lock is a blocking call, so it's recommended to run it in a goroutine.
func (Client) Watch ¶
Watch will create a watch on a lock and push value changes into the valueChanges channel. An empty string indicates the lack of a lock. Pushing true into quit will end the watch.
valueChanges := make(chan string) go client.Watch("my-service", valueChanges, nil) for { select { case v := <-valueChanges: fmt.Printf("Lock value changed: %s\n", v) } }
Watch is a blocking call, so it's recommended to run it in a goroutine.
type EtcdStore ¶
type EtcdStore struct { EtcdClientv3 *clientv3.Client // Version of the etcd Version string // TTL is the time-to-live for the lock. Default: 5s. TTL int64 Log log.Logger }
EtcdStore is a backing store for Locker which uses Etcd for storage.
func (EtcdStore) AcquireOrFreshenLock ¶
AcquireOrFreshenLock will aquires a named lock if it isn't already held, or updates its TTL if it is.
type LockDenied ¶
type LockDenied struct {
// contains filtered or unexported fields
}
LockDenied is returned when a lock is attempted on a key which has been acquired by another client.
func (LockDenied) Error ¶
func (e LockDenied) Error() string
type LockNotFound ¶
type LockNotFound struct {
// contains filtered or unexported fields
}
LockNotFound is returned when a Get is made against a key which isn't locked.
func (LockNotFound) Error ¶
func (e LockNotFound) Error() string
type Store ¶
type Store interface { // Get returns the value of a lock. LockNotFound will be returned if a // lock with the name isn't held. Get(ctx context.Context, name string) (string, error) // AcquireOrFreshenLock will aquires a named lock if it isn't already // held, or updates its TTL if it is. AcquireOrFreshenLock(ctx context.Context, name, value string) error Delete(ctx context.Context, name string) error }
Store is a persistance mechaism for locker to store locks. Needs to be able to support querying and an atomic compare-and-swap. Currently, the only implementation of a Store is EtcdStore.