diff --git a/pkg/gotd/pool/pool.go b/pkg/gotd/pool/pool.go index 449c856f2..437b71e78 100644 --- a/pkg/gotd/pool/pool.go +++ b/pkg/gotd/pool/pool.go @@ -207,11 +207,9 @@ retry: case <-c.stuck.Ready(): c.log.Debug("Some connection dead, try to create new connection, cancel waiting") - c.freeReq.delete(key) - select { - default: - case conn, ok := <-ch: - if ok && conn != nil { + if !c.freeReq.delete(key) { + // transfer took the request, so a connection is on its way and must not be dropped. + if conn, ok := <-ch; ok && conn != nil { return conn, nil } } @@ -224,11 +222,10 @@ retry: } // Executed only if at least one of context is Done. - c.freeReq.delete(key) - select { - default: - case conn, ok := <-ch: - if ok && conn != nil { + if !c.freeReq.delete(key) { + // transfer took the request, so a connection is on its way and must be given back to the + // pool instead of being left in the channel. + if conn, ok := <-ch; ok && conn != nil { c.release(conn) } } diff --git a/pkg/gotd/pool/req_map.go b/pkg/gotd/pool/req_map.go index 38e6af10a..f5592becb 100644 --- a/pkg/gotd/pool/req_map.go +++ b/pkg/gotd/pool/req_map.go @@ -56,8 +56,12 @@ func (r *reqMap) transfer(c *poolConn) bool { return true } -func (r *reqMap) delete(key reqKey) { +// delete removes the pending request. It returns false if transfer already claimed the request, +// which means a connection is about to be sent to the request channel. +func (r *reqMap) delete(key reqKey) bool { r.mux.Lock() + _, ok := r.m[key] delete(r.m, key) r.mux.Unlock() + return ok }