diff options
author | 2023-04-29 17:44:20 +0100 | |
---|---|---|
committer | 2023-04-29 18:44:20 +0200 | |
commit | 68b91d2128c7be3c4f060091b172c39057318ad4 (patch) | |
tree | 3bcf4af8fa79b43f56857df4bba1453977fa01b3 /internal/httpclient/client.go | |
parent | [feature] Add GET endpoint for single notification (#1719) (diff) | |
download | gotosocial-68b91d2128c7be3c4f060091b172c39057318ad4.tar.xz |
[performance] tweak http client error handling (#1718)
* update errors library, check for more TLS type error in http client
Signed-off-by: kim <grufwub@gmail.com>
* bump cache library version to match errors library
Signed-off-by: kim <grufwub@gmail.com>
---------
Signed-off-by: kim <grufwub@gmail.com>
Diffstat (limited to 'internal/httpclient/client.go')
-rw-r--r-- | internal/httpclient/client.go | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/internal/httpclient/client.go b/internal/httpclient/client.go index 67a1d0715..68e11495d 100644 --- a/internal/httpclient/client.go +++ b/internal/httpclient/client.go @@ -149,7 +149,7 @@ func New(cfg Config) *Client { // Initiate outgoing bad hosts lookup cache. c.badHosts = cache.New[string, struct{}](0, 1000, 0) - c.badHosts.SetTTL(15*time.Minute, false) + c.badHosts.SetTTL(time.Hour, false) if !c.badHosts.Start(time.Minute) { log.Panic(nil, "failed to start transport controller cache") } @@ -165,7 +165,7 @@ func (c *Client) Do(r *http.Request) (*http.Response, error) { } // DoSigned ... -func (c *Client) DoSigned(r *http.Request, sign SignFunc) (*http.Response, error) { +func (c *Client) DoSigned(r *http.Request, sign SignFunc) (rsp *http.Response, err error) { const ( // max no. attempts. maxRetries = 5 @@ -182,10 +182,16 @@ func (c *Client) DoSigned(r *http.Request, sign SignFunc) (*http.Response, error if !fastFail { // Check if recently reached max retries for this host // so we don't bother with a retry-backoff loop. The only - // errors that are retried upon are server failure and - // domain resolution type errors, so this cached result + // errors that are retried upon are server failure, TLS + // and domain resolution type errors, so this cached result // indicates this server is likely having issues. fastFail = c.badHosts.Has(host) + defer func() { + if err != nil { + // On error return mark as bad-host. + c.badHosts.Set(host, struct{}{}) + } + }() } // Start a log entry for this request @@ -218,7 +224,7 @@ func (c *Client) DoSigned(r *http.Request, sign SignFunc) (*http.Response, error l.Infof("performing request") // Perform the request. - rsp, err := c.do(r) + rsp, err = c.do(r) if err == nil { //nolint:gocritic // TooManyRequest means we need to slow @@ -249,20 +255,27 @@ func (c *Client) DoSigned(r *http.Request, sign SignFunc) (*http.Response, error } } - } else if errorsv2.Is(err, + // Ensure unset. + rsp = nil + + } else if errorsv2.Comparable(err, context.DeadlineExceeded, context.Canceled, ErrBodyTooLarge, ErrReservedAddr, ) { - // Return on non-retryable errors + // Non-retryable errors. + return nil, err + } else if errorsv2.Assignable(err, + (*x509.CertificateInvalidError)(nil), + (*x509.HostnameError)(nil), + (*x509.UnknownAuthorityError)(nil), + ) { + // Non-retryable TLS errors. return nil, err } else if strings.Contains(err.Error(), "stopped after 10 redirects") { // Don't bother if net/http returned after too many redirects return nil, err - } else if errors.As(err, &x509.UnknownAuthorityError{}) { - // Unknown authority errors we do NOT recover from - return nil, err } else if dnserr := (*net.DNSError)(nil); // nocollapse errors.As(err, &dnserr) && dnserr.IsNotFound { // DNS lookup failure, this domain does not exist @@ -292,10 +305,9 @@ func (c *Client) DoSigned(r *http.Request, sign SignFunc) (*http.Response, error } } - // Add "bad" entry for this host. - c.badHosts.Set(host, struct{}{}) - - return nil, errors.New("transport reached max retries") + // Set error return to trigger setting "bad host". + err = errors.New("transport reached max retries") + return } // do ... |