Skip to content

Commit

Permalink
[chore] transport improvements (#1524)
Browse files Browse the repository at this point in the history
* improve error readability, mark "bad hosts" as fastFail

Signed-off-by: kim <grufwub@gmail.com>

* pull in latest go-byteutil version with byteutil.Reader{}

Signed-off-by: kim <grufwub@gmail.com>

* use rewindable body reader for post requests

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
  • Loading branch information
NyaaaWhatsUpDoc committed Feb 18, 2023
1 parent 3649b23 commit a684fc4
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 63 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.19

require (
codeberg.org/gruf/go-bytesize v1.0.2
codeberg.org/gruf/go-byteutil v1.0.2
codeberg.org/gruf/go-byteutil v1.1.2
codeberg.org/gruf/go-cache/v3 v3.2.2
codeberg.org/gruf/go-debug v1.3.0
codeberg.org/gruf/go-errors/v2 v2.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ codeberg.org/gruf/go-bytes v1.0.2/go.mod h1:1v/ibfaosfXSZtRdW2rWaVrDXMc9E3bsi/M9
codeberg.org/gruf/go-bytesize v1.0.2 h1:Mo+ITi+0uZ4YNSZf2ed6Qw8acOI39W4mmgE1a8lslXw=
codeberg.org/gruf/go-bytesize v1.0.2/go.mod h1:n/GU8HzL9f3UNp/mUKyr1qVmTlj7+xacpp0OHfkvLPs=
codeberg.org/gruf/go-byteutil v1.0.0/go.mod h1:cWM3tgMCroSzqoBXUXMhvxTxYJp+TbCr6ioISRY5vSU=
codeberg.org/gruf/go-byteutil v1.0.2 h1:OesVyK5VKWeWdeDR00zRJ+Oy8hjXx1pBhn7WVvcZWVE=
codeberg.org/gruf/go-byteutil v1.0.2/go.mod h1:cWM3tgMCroSzqoBXUXMhvxTxYJp+TbCr6ioISRY5vSU=
codeberg.org/gruf/go-byteutil v1.1.2 h1:TQLZtTxTNca9xEfDIndmo7nBYxeS94nrv/9DS3Nk5Tw=
codeberg.org/gruf/go-byteutil v1.1.2/go.mod h1:cWM3tgMCroSzqoBXUXMhvxTxYJp+TbCr6ioISRY5vSU=
codeberg.org/gruf/go-cache/v3 v3.2.2 h1:hq6/RITgpcArjzbYSyo3uFxfIw7wW3KqAQjEaN7dj58=
codeberg.org/gruf/go-cache/v3 v3.2.2/go.mod h1:+Eje6nCvN8QF71VyYjMWMnkdv6t1kHnCO/SvyC4K12Q=
codeberg.org/gruf/go-debug v1.3.0 h1:PIRxQiWUFKtGOGZFdZ3Y0pqyfI0Xr87j224IYe2snZs=
Expand Down
12 changes: 8 additions & 4 deletions internal/transport/deliver.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
package transport

import (
"bytes"
"context"
"fmt"
"net/http"
"net/url"
"strings"
"sync"

"codeberg.org/gruf/go-byteutil"
apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
"github.com/superseriousbusiness/gotosocial/internal/config"
)
Expand All @@ -49,7 +49,7 @@ func (t *transport) BatchDeliver(ctx context.Context, b []byte, recipients []*ur
wg.Wait()

// receive any buffered errors
errs := make([]string, 0, len(recipients))
errs := make([]string, 0, len(errCh))
outer:
for {
select {
Expand All @@ -75,7 +75,11 @@ func (t *transport) Deliver(ctx context.Context, b []byte, to *url.URL) error {

urlStr := to.String()

req, err := http.NewRequestWithContext(ctx, "POST", urlStr, bytes.NewReader(b))
// Use rewindable bytes reader for body.
var body byteutil.ReadNopCloser
body.Reset(b)

req, err := http.NewRequestWithContext(ctx, "POST", urlStr, &body)
if err != nil {
return err
}
Expand All @@ -92,7 +96,7 @@ func (t *transport) Deliver(ctx context.Context, b []byte, to *url.URL) error {

if code := resp.StatusCode; code != http.StatusOK &&
code != http.StatusCreated && code != http.StatusAccepted {
return fmt.Errorf("POST request to %s failed (%d): %s", urlStr, resp.StatusCode, resp.Status)
return fmt.Errorf("POST request to %s failed: %s", urlStr, resp.Status)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion internal/transport/dereference.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,6 @@ func (t *transport) Dereference(ctx context.Context, iri *url.URL) ([]byte, erro
case http.StatusGone:
return nil, ErrGone
default:
return nil, fmt.Errorf("GET request to %s failed (%d): %s", iriStr, rsp.StatusCode, rsp.Status)
return nil, fmt.Errorf("GET request to %s failed: %s", iriStr, rsp.Status)
}
}
6 changes: 3 additions & 3 deletions internal/transport/derefinstance.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func dereferenceByAPIV1Instance(ctx context.Context, t *transport, iri *url.URL)
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("GET request to %s failed (%d): %s", iriStr, resp.StatusCode, resp.Status)
return nil, fmt.Errorf("GET request to %s failed: %s", iriStr, resp.Status)
}

b, err := io.ReadAll(resp.Body)
Expand Down Expand Up @@ -252,7 +252,7 @@ func callNodeInfoWellKnown(ctx context.Context, t *transport, iri *url.URL) (*ur
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("callNodeInfoWellKnown: GET request to %s failed (%d): %s", iriStr, resp.StatusCode, resp.Status)
return nil, fmt.Errorf("callNodeInfoWellKnown: GET request to %s failed: %s", iriStr, resp.Status)
}

b, err := io.ReadAll(resp.Body)
Expand Down Expand Up @@ -303,7 +303,7 @@ func callNodeInfo(ctx context.Context, t *transport, iri *url.URL) (*apimodel.No
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("callNodeInfo: GET request to %s failed (%d): %s", iriStr, resp.StatusCode, resp.Status)
return nil, fmt.Errorf("callNodeInfo: GET request to %s failed: %s", iriStr, resp.Status)
}

b, err := io.ReadAll(resp.Body)
Expand Down
2 changes: 1 addition & 1 deletion internal/transport/derefmedia.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (t *transport) DereferenceMedia(ctx context.Context, iri *url.URL) (io.Read

// Check for an expected status code
if rsp.StatusCode != http.StatusOK {
return nil, 0, fmt.Errorf("GET request to %s failed (%d): %s", iriStr, rsp.StatusCode, rsp.Status)
return nil, 0, fmt.Errorf("GET request to %s failed: %s", iriStr, rsp.Status)
}

return rsp.Body, rsp.ContentLength, nil
Expand Down
2 changes: 1 addition & 1 deletion internal/transport/finger.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (t *transport) Finger(ctx context.Context, targetUsername string, targetDom

// Check for an expected status code
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("GET request to %s failed (%d): %s", urlStr, rsp.StatusCode, rsp.Status)
return nil, fmt.Errorf("GET request to %s failed: %s", urlStr, rsp.Status)
}

return io.ReadAll(rsp.Body)
Expand Down
30 changes: 18 additions & 12 deletions internal/transport/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"sync"
"time"

"codeberg.org/gruf/go-byteutil"
errorsv2 "codeberg.org/gruf/go-errors/v2"
"codeberg.org/gruf/go-kv"
"github.com/go-fed/httpsig"
Expand Down Expand Up @@ -84,7 +85,7 @@ type transport struct {
signerMu sync.Mutex
}

// GET will perform given http request using transport client, retrying on certain preset errors, or if status code is among retryOn.
// GET will perform given http request using transport client, retrying on certain preset errors.
func (t *transport) GET(r *http.Request) (*http.Response, error) {
if r.Method != http.MethodGet {
return nil, errors.New("must be GET request")
Expand All @@ -94,7 +95,7 @@ func (t *transport) GET(r *http.Request) (*http.Response, error) {
})
}

// POST will perform given http request using transport client, retrying on certain preset errors, or if status code is among retryOn.
// POST will perform given http request using transport client, retrying on certain preset errors.
func (t *transport) POST(r *http.Request, body []byte) (*http.Response, error) {
if r.Method != http.MethodPost {
return nil, errors.New("must be POST request")
Expand All @@ -116,18 +117,17 @@ func (t *transport) do(r *http.Request, signer func(*http.Request) error) (*http
// Get request hostname
host := r.URL.Hostname()

// Check if recently reached max retries for this host
// so we don't need to bother reattempting it. The only
// errors that are retried upon are server failure and
// domain resolution type errors, so this cached result
// indicates this server is likely having issues.
if t.controller.badHosts.Has(host) {
return nil, errors.New("too many failed attempts")
}

// Check whether request should fast fail, we check this
// before loop as each context.Value() requires mutex lock.
fastFail := IsFastfail(r.Context())
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
// indicates this server is likely having issues.
fastFail = t.controller.badHosts.Has(host)
}

// Start a log entry for this request
l := log.WithContext(r.Context()).
Expand All @@ -148,6 +148,12 @@ func (t *transport) do(r *http.Request, signer func(*http.Request) error) (*http
r.Header.Del("Signature")
r.Header.Del("Digest")

// Rewind body reader and content-length if set.
if rc, ok := r.Body.(*byteutil.ReadNopCloser); ok {
r.ContentLength = int64(rc.Len())
rc.Rewind()
}

// Perform request signing
if err := signer(r); err != nil {
return nil, err
Expand Down Expand Up @@ -226,7 +232,7 @@ func (t *transport) do(r *http.Request, signer func(*http.Request) error) (*http
}
}

// Add "bad" entry for this host
// Add "bad" entry for this host.
t.controller.badHosts.Set(host, struct{}{})

return nil, errors.New("transport reached max retries")
Expand Down
49 changes: 12 additions & 37 deletions vendor/codeberg.org/gruf/go-byteutil/bytes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions vendor/codeberg.org/gruf/go-byteutil/reader.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ codeberg.org/gruf/go-bytes
# codeberg.org/gruf/go-bytesize v1.0.2
## explicit; go 1.17
codeberg.org/gruf/go-bytesize
# codeberg.org/gruf/go-byteutil v1.0.2
# codeberg.org/gruf/go-byteutil v1.1.2
## explicit; go 1.16
codeberg.org/gruf/go-byteutil
# codeberg.org/gruf/go-cache/v3 v3.2.2
Expand Down

0 comments on commit a684fc4

Please sign in to comment.