Skip to content

Commit

Permalink
Retries for media fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
vurpo committed Jul 3, 2023
1 parent e99578a commit d0d641d
Showing 1 changed file with 64 additions and 14 deletions.
78 changes: 64 additions & 14 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1386,30 +1386,80 @@ func (cli *Client) DownloadContext(ctx context.Context, mxcURL id.ContentURI) (i
return resp.Body, nil
}

func (cli *Client) doMediaRetry(req *http.Request, cause error, retries int, backoff time.Duration) (*http.Response, error) {
log := zerolog.Ctx(req.Context())
if req.Body != nil {
if req.GetBody == nil {
log.Warn().Msg("Failed to get new body to retry request: GetBody is nil")
return nil, cause
}
var err error
req.Body, err = req.GetBody()
if err != nil {
log.Warn().Err(err).Msg("Failed to get new body to retry request")
return nil, cause
}
}
log.Warn().Err(cause).
Int("retry_in_seconds", int(backoff.Seconds())).
Msg("Request failed, retrying")
time.Sleep(backoff)
return cli.doMediaRequest(req, retries-1, backoff*2)
}

func (cli *Client) doMediaRequest(req *http.Request, retries int, backoff time.Duration) (*http.Response, error) {
cli.RequestStart(req)
startTime := time.Now()
res, err := cli.Client.Do(req)
duration := time.Now().Sub(startTime)
if res != nil {
defer res.Body.Close()
}
if err != nil {
if retries > 0 {
return cli.doMediaRetry(req, err, retries, backoff)
}
err = HTTPError{
Request: req,
Response: res,

Message: "request error",
WrappedError: err,
}
cli.LogRequestDone(req, res, err, nil, 0, duration)
return nil, err
}

if retries > 0 && cli.shouldRetry(res) {
if res.StatusCode == http.StatusTooManyRequests {
backoff = parseBackoffFromResponse(req, res, time.Now(), backoff)
}
return cli.doMediaRetry(req, fmt.Errorf("HTTP %d", res.StatusCode), retries, backoff)
}

var body []byte
if res.StatusCode < 200 || res.StatusCode >= 300 {
body, err = ParseErrorResponse(req, res)
cli.LogRequestDone(req, res, err, nil, len(body), duration)
} else {
cli.LogRequestDone(req, res, nil, nil, -1, duration)
}
return res, err
}

func (cli *Client) downloadContext(ctx context.Context, mxcURL id.ContentURI) (*http.Response, error) {
ctxLog := zerolog.Ctx(ctx)
if ctxLog.GetLevel() == zerolog.Disabled || ctxLog == zerolog.DefaultContextLogger {
ctx = cli.Log.WithContext(ctx)
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, cli.GetDownloadURL(mxcURL), nil)
if err != nil {
return nil, err
}
req.Header.Set("User-Agent", cli.UserAgent+" (media downloader)")
cli.RequestStart(req)
downloadStart := time.Now()
if resp, err := cli.Client.Do(req); err != nil {
cli.LogRequestDone(req, resp, err, nil, 0, time.Since(downloadStart))
return nil, err
} else if resp.StatusCode < 200 || resp.StatusCode >= 300 {
body, err := ParseErrorResponse(req, resp)
_ = resp.Body.Close()
cli.LogRequestDone(req, resp, err, nil, len(body), time.Since(downloadStart))
return nil, err
} else {
cli.LogRequestDone(req, resp, nil, nil, -1, time.Since(downloadStart))
return resp, nil
}
resp, err := cli.doMediaRequest(req, cli.DefaultHTTPRetries, 4*time.Second)
return resp, err
}

func (cli *Client) DownloadBytes(mxcURL id.ContentURI) ([]byte, error) {
Expand Down

0 comments on commit d0d641d

Please sign in to comment.