Skip to content

Commit

Permalink
Add optional temporary error handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
devnev committed Jul 12, 2019
1 parent cc309e4 commit c8c216b
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions listener_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ package conntrack
import (
"fmt"
"net"

"sync"

"github.com/jpillora/backoff"
"golang.org/x/net/trace"
"time"
)
Expand All @@ -22,6 +22,7 @@ type listenerOpts struct {
monitoring bool
tracing bool
tcpKeepAlive time.Duration
retryBackoff *backoff.Backoff
}

type listenerOpt func(*listenerOpts)
Expand All @@ -47,6 +48,14 @@ func TrackWithTracing() listenerOpt {
}
}

// TrackWithRetries enables retrying of temporary Accept() errors, with the given backoff between attempts.
// Concurrent accept calls that receive temporary errors have independent backoff scaling.
func TrackWithRetries(b backoff.Backoff) listenerOpt {
return func(opts *listenerOpts) {
opts.retryBackoff = &b
}
}

// TrackWithTcpKeepAlive makes sure that any `net.TCPConn` that get accepted have a keep-alive.
// This is useful for HTTP servers in order for, for example laptops, to not use up resources on the
// server while they don't utilise their connection.
Expand Down Expand Up @@ -83,7 +92,20 @@ func NewListener(inner net.Listener, optFuncs ...listenerOpt) net.Listener {

func (ct *connTrackListener) Accept() (net.Conn, error) {
// TODO(mwitkow): Add monitoring of failed accept.
conn, err := ct.Listener.Accept()
var (
conn net.Conn
err error
)
for attempt := 0; ; attempt++ {
conn, err = ct.Listener.Accept()
if err == nil || ct.opts.retryBackoff == nil {
break
}
if t, ok := err.(interface{ Temporary() bool }); !ok || !t.Temporary() {
break
}
time.Sleep(ct.opts.retryBackoff.ForAttempt(float64(attempt)))
}
if err != nil {
return nil, err
}
Expand All @@ -102,7 +124,6 @@ type serverConnTracker struct {
}

func newServerConnTracker(inner net.Conn, opts *listenerOpts) net.Conn {

tracker := &serverConnTracker{
Conn: inner,
opts: opts,
Expand Down

0 comments on commit c8c216b

Please sign in to comment.