func main() { var normal tec.TempErrCatcher var skipper tec.TempErrCatcher skipper.IsTemp = func(e error) bool { return e == ErrSkip } fmt.Println("trying normal (uses Temporary interface)") tryTec(normal) fmt.Println("") fmt.Println("trying skipper (uses our IsTemp function)") tryTec(skipper) }
// accept continously accepts incoming connections and // adds them to the listener's Swarm. is is meant to be // run in a goroutine. // TODO: add rate limiting func (l *Listener) accept() { var wg sync.WaitGroup defer func() { wg.Wait() // must happen before teardown l.teardown() }() // catching the error here is odd. doing what net/http does: // http://golang.org/src/net/http/server.go?s=51504:51550#L1728 // Using the lib: https://godoc.org/github.com/jbenet/go-temp-err-catcher var catcher tec.TempErrCatcher // rate limit concurrency limit := make(chan struct{}, AcceptConcurrency) // loop forever accepting connections for { conn, err := l.netList.Accept() if err != nil { if catcher.IsTemporary(err) { continue } l.acceptErr <- fmt.Errorf("peerstream listener failed: %s", err) return // ok, problems. bail. } // add conn to swarm and listen for incoming streams // do this in a goroutine to avoid blocking the Accept loop. // note that this does not rate limit accepts. limit <- struct{}{} // sema down wg.Add(1) go func(conn net.Conn) { defer func() { <-limit }() // sema up defer wg.Done() conn2, err := l.swarm.addConn(conn, true) if err != nil { l.acceptErr <- err return } conn2.groups.AddSet(&l.groups) // add out groups }(conn) } }
func tryTec(c tec.TempErrCatcher) { errs := []error{ ErrTemp, ErrSkip, ErrOther, ErrTemp, ErrSkip, ErrOther, } for _, e := range errs { if c.IsTemporary(e) { fmt.Printf("\tIsTemporary: true - skipped %s\n", e) continue } fmt.Printf("\tIsTemporary: false - not skipped %s\n", e) } }