diff --git a/ldap/search.go b/ldap/search.go index 872f6fec3fdb2a8516f7e3da55dddeb972b358f5..db29ba092ea0cb1e1be3db3a753c75c7e1188f3f 100644 --- a/ldap/search.go +++ b/ldap/search.go @@ -10,16 +10,24 @@ import ( "git.autistici.org/ai3/go-common/clientutil" ) -// Treat all errors as potential network-level issues, except for a -// whitelist of LDAP protocol level errors that we know are benign. +// Interface matched by net.Error. +type hasTemporary interface { + Temporary() bool +} + +// Treat network errors as temporary. Other errors are permanent by +// default. func isTemporaryLDAPError(err error) bool { - ldapErr, ok := err.(*ldap.Error) - if !ok { - return true - } - switch ldapErr.ResultCode { - case ldap.ErrorNetwork: - return true + switch v := err.(type) { + case *ldap.Error: + switch v.ResultCode { + case ldap.ErrorNetwork: + return true + default: + return false + } + case hasTemporary: + return v.Temporary() default: return false } @@ -32,6 +40,7 @@ func (p *ConnectionPool) Search(ctx context.Context, searchRequest *ldap.SearchR err := clientutil.Retry(func() error { conn, err := p.Get(ctx) if err != nil { + // Here conn is nil, so we don't need to Release it. if isTemporaryLDAPError(err) { return clientutil.TempError(err) } @@ -44,7 +53,7 @@ func (p *ConnectionPool) Search(ctx context.Context, searchRequest *ldap.SearchR result, err = conn.Search(searchRequest) if err != nil && isTemporaryLDAPError(err) { - p.Release(conn, nil) + p.Release(conn, err) return clientutil.TempError(err) } p.Release(conn, err)