Codebase list golang-github-go-kit-kit / 83e9f21
util: documentation updates Peter Bourgon 7 years ago
3 changed file(s) with 36 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
0 # util
1
2 This directory holds packages of general utility to multiple consumers within Go kit,
3 and potentially other consumers in the wider Go ecosystem.
4 There is no `package util` and will never be.
0 // Package conn provides utilities related to connections.
1 package conn
66 "github.com/go-kit/kit/log"
77 )
88
9 // Dialer dials a network and address. net.Dial is a good default Dialer.
9 // Dialer imitates net.Dial. Dialer is assumed to yield connections that are
10 // safe for use by multiple concurrent goroutines.
1011 type Dialer func(network, address string) (net.Conn, error)
1112
1213 // AfterFunc imitates time.After.
1314 type AfterFunc func(time.Duration) <-chan time.Time
1415
15 // Manager manages a net.Conn. Clients should take the conn when they want to
16 // use it, and put back whatever error they receive from an e.g. Write. When a
17 // non-nil error is put, the conn is invalidated and a new conn is established.
16 // Manager manages a net.Conn.
17 //
18 // Clients provide a way to create the connection with a Dialer, network, and
19 // address. Clients should Take the connection when they want to use it, and Put
20 // back whatever error they receive from its use. When a non-nil error is Put,
21 // the connection is invalidated, and a new connection is established.
1822 // Connection failures are retried after an exponential backoff.
1923 type Manager struct {
20 dial Dialer
24 dialer Dialer
2125 network string
2226 address string
2327 after AfterFunc
2731 putc chan error
2832 }
2933
34 // NewManager returns a connection manager using the passed Dialer, network, and
35 // address. The AfterFunc is used to control exponential backoff and retries.
36 // For normal use, pass net.Dial and time.After as the Dialer and AfterFunc
37 // respectively. The logger is used to log errors; pass a log.NopLogger if you
38 // don't care to receive them.
3039 func NewManager(d Dialer, network, address string, after AfterFunc, logger log.Logger) *Manager {
3140 m := &Manager{
32 dial: d,
41 dialer: d,
3342 network: network,
3443 address: address,
3544 after: after,
4251 return m
4352 }
4453
54 // Take yields the current connection. It may be nil.
4555 func (m *Manager) Take() net.Conn {
4656 return <-m.takec
4757 }
4858
59 // Put accepts an error that came from a previously yielded connection. If the
60 // error is non-nil, the manager will invalidate the current connection and try
61 // to reconnect, with exponential backoff. Putting a nil error is a no-op.
4962 func (m *Manager) Put(err error) {
5063 m.putc <- err
5164 }
5265
5366 func (m *Manager) loop() {
5467 var (
55 conn = dial(m.dial, m.network, m.address, m.logger) // may block slightly
68 conn = dial(m.dialer, m.network, m.address, m.logger) // may block slightly
5669 connc = make(chan net.Conn)
5770 reconnectc <-chan time.Time // initially nil
5871 backoff = time.Second
6174 for {
6275 select {
6376 case <-reconnectc:
64 reconnectc = nil
65 go func() { connc <- dial(m.dial, m.network, m.address, m.logger) }()
77 reconnectc = nil // one-shot
78 go func() { connc <- dial(m.dialer, m.network, m.address, m.logger) }()
6679
6780 case conn = <-connc:
6881 if conn == nil {
69 backoff = exponential(backoff)
70 reconnectc = m.after(backoff)
82 // didn't work
83 backoff = exponential(backoff) // wait longer
84 reconnectc = m.after(backoff) // try again
7185 } else {
72 backoff = time.Second
73 reconnectc = nil
86 // worked!
87 backoff = time.Second // reset wait time
88 reconnectc = nil // no retry necessary
7489 }
7590
7691 case m.takec <- conn:
77 // might be nil
7892
7993 case err := <-m.putc:
8094 if err != nil && conn != nil {
90104 conn, err := d(network, address)
91105 if err != nil {
92106 logger.Log("err", err)
93 conn = nil
107 conn = nil // just to be sure
94108 }
95109 return conn
96110 }