Skip to content
Snippets Groups Projects
Commit fd4b1c84 authored by ale's avatar ale
Browse files

more documentation

parent b0c130c5
No related branches found
No related tags found
No related merge requests found
// Package masterelection lets you run a simple master-election
// protocol on top of etcd.
package masterelection package masterelection
import ( import (
...@@ -16,6 +18,9 @@ const ( ...@@ -16,6 +18,9 @@ const (
RoleMaster RoleMaster
) )
// How long to sleep on etcd Create() errors.
var errorDelay = 200 * time.Millisecond
// Role of a participant in the master election protocol. // Role of a participant in the master election protocol.
type Role int type Role int
...@@ -213,6 +218,7 @@ func (m *MasterElection) runSlave(index uint64, stop chan bool) { ...@@ -213,6 +218,7 @@ func (m *MasterElection) runSlave(index uint64, stop chan bool) {
// Run the master election protocol, until the stop channel is closed. // Run the master election protocol, until the stop channel is closed.
func (m *MasterElection) Run(stop chan bool) { func (m *MasterElection) Run(stop chan bool) {
// If an update channel is set, close it on exit.
if m.stateCh != nil { if m.stateCh != nil {
defer close(m.stateCh) defer close(m.stateCh)
} }
...@@ -242,7 +248,7 @@ func (m *MasterElection) Run(stop chan bool) { ...@@ -242,7 +248,7 @@ func (m *MasterElection) Run(stop chan bool) {
} else { } else {
// An error of some other sort! Retry. // An error of some other sort! Retry.
m.Log.Printf("unexpected error: %v", err) m.Log.Printf("unexpected error: %v", err)
time.Sleep(errorDelay)
} }
} }
} }
// Package presence allows individual nodes in a cluster to let their
// presence known to other peers through a central registry (a
// directory on etcd). Nodes can store a small amount of information
// along with their state.
//
package presence package presence
import ( import (
...@@ -23,6 +28,8 @@ type Client struct { ...@@ -23,6 +28,8 @@ type Client struct {
path string path string
} }
// NewClient returns a simple client that can look up the registry and
// return a list of active nodes.
func NewClient(client EtcdClient, path string) *Client { func NewClient(client EtcdClient, path string) *Client {
return &Client{ return &Client{
client: client, client: client,
...@@ -58,7 +65,8 @@ type Presence struct { ...@@ -58,7 +65,8 @@ type Presence struct {
} }
// New returns a new Presence worker that establishes node presence at // New returns a new Presence worker that establishes node presence at
// the specified path. // the specified path. It will create a new unique file below that
// directory, and remove it when Stop() is called (or the TTL expires).
func New(client EtcdClient, path string, stateFn StateFn, ttl uint64) *Presence { func New(client EtcdClient, path string, stateFn StateFn, ttl uint64) *Presence {
return &Presence{ return &Presence{
Client: NewClient(client, path), Client: NewClient(client, path),
......
...@@ -12,6 +12,10 @@ type hasClose interface { ...@@ -12,6 +12,10 @@ type hasClose interface {
Close() error Close() error
} }
// Cache for data that is expensive to decode. Keeps the (decoded)
// contents of the remote etcd directory in memory. Uses a DecodeFn to
// parse the encoded data stored in etcd only when it is actually
// modified.
type Cache struct { type Cache struct {
w *Watcher w *Watcher
decodeFn DecodeFn decodeFn DecodeFn
...@@ -25,6 +29,7 @@ func defaultDecodeFn(value string) interface{} { ...@@ -25,6 +29,7 @@ func defaultDecodeFn(value string) interface{} {
return value return value
} }
// NewCache returns a new Cache mirroring 'path'.
func NewCache(client EtcdClient, path string, decodeFn DecodeFn) *Cache { func NewCache(client EtcdClient, path string, decodeFn DecodeFn) *Cache {
if decodeFn == nil { if decodeFn == nil {
decodeFn = defaultDecodeFn decodeFn = defaultDecodeFn
...@@ -44,6 +49,7 @@ func NewCache(client EtcdClient, path string, decodeFn DecodeFn) *Cache { ...@@ -44,6 +49,7 @@ func NewCache(client EtcdClient, path string, decodeFn DecodeFn) *Cache {
return c return c
} }
// Close the Cache and release associated resources.
func (c *Cache) Close() { func (c *Cache) Close() {
c.w.Stop() c.w.Stop()
} }
...@@ -90,6 +96,7 @@ func (c *Cache) handleResponse(resp *etcd.Response) { ...@@ -90,6 +96,7 @@ func (c *Cache) handleResponse(resp *etcd.Response) {
c.lock.Unlock() c.lock.Unlock()
} }
// Get a value from the cache.
func (c *Cache) Get(key string) (interface{}, bool) { func (c *Cache) Get(key string) (interface{}, bool) {
c.lock.RLock() c.lock.RLock()
value, ok := c.data[key] value, ok := c.data[key]
...@@ -97,6 +104,7 @@ func (c *Cache) Get(key string) (interface{}, bool) { ...@@ -97,6 +104,7 @@ func (c *Cache) Get(key string) (interface{}, bool) {
return value, ok return value, ok
} }
// Get a value and the associated etcd index.
func (c *Cache) GetWithIndex(key string) (interface{}, uint64, bool) { func (c *Cache) GetWithIndex(key string) (interface{}, uint64, bool) {
c.lock.RLock() c.lock.RLock()
index := c.index index := c.index
......
// Package watcher monitors a path on etcd for changes, and sends them
// on a channel. It can thus build a local in-memory cache of the
// contents of the etcd directory, which is convenient for small
// datasets that don't change often (configuration data, for
// instance).
//
// The package includes both a simple cache implementation (Cache),
// and a background worker to synchronize arbitrary objects
// implementing the Syncable interface (Syncer).
//
package watcher package watcher
import ( import (
......
#!/bin/sh
#
# Test that the running autoradio cluster on Vagrant is performing
# as expected.
#
expected_dns="192.168.50.2 192.168.50.3 192.168.50.4"
dns=$(dig +short stream.autora.dio @192.168.50.3 | sort | tr '\n' ' ' | sed -e 's/ $//')
if [ "$dns" != "$expected_dns" ]; then
echo "DNS query for stream.autora.dio did not return expected results: ${expected_dns}" >&2
exit 1
fi
echo "Vagrant autoradio cluster looks ok." >&2
exit 0
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment