Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Commit

Permalink
feat: common .RetryAfter() interface for errors (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias authored Mar 8, 2023
1 parent 17d3c38 commit e621c98
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 23 deletions.
20 changes: 13 additions & 7 deletions caboose.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,25 +104,31 @@ var ErrSaturnTimeout error = errors.New("saturn backend timed out")

type ErrSaturnTooManyRequests struct {
Node string
RetryAfter time.Duration // TODO: DRY refactor after https://github.com/ipfs/go-libipfs/issues/188
retryAfter time.Duration
}

func (e ErrSaturnTooManyRequests) Error() string {
return fmt.Sprintf("saturn node %s returned Too Many Requests error, please retry after %s", e.Node, humanRetry(e.RetryAfter))
func (e *ErrSaturnTooManyRequests) Error() string {
return fmt.Sprintf("saturn node %s returned Too Many Requests error, please retry after %s", e.Node, humanRetry(e.retryAfter))
}

func (e *ErrSaturnTooManyRequests) RetryAfter() time.Duration {
return e.retryAfter
}

type ErrCoolDown struct {
Cid cid.Cid
Path string
RetryAfter time.Duration // TODO: DRY refactor after https://github.com/ipfs/go-libipfs/issues/188
retryAfter time.Duration
}

func (e *ErrCoolDown) Error() string {
return fmt.Sprintf("multiple saturn retrieval failures seen for CID %s/Path %s, please retry after %s", e.Cid, e.Path, humanRetry(e.RetryAfter))
return fmt.Sprintf("multiple saturn retrieval failures seen for CID %s/Path %s, please retry after %s", e.Cid, e.Path, humanRetry(e.retryAfter))
}

func (e *ErrCoolDown) RetryAfter() time.Duration {
return e.retryAfter
}

// TODO: move this to upstream error interface in https://github.com/ipfs/go-libipfs/issues/188
// and refactor ErrCoolDown and ErrSaturnTooManyRequests to inherit from that instead
func humanRetry(d time.Duration) string {
return d.Truncate(time.Second).String()
}
Expand Down
15 changes: 10 additions & 5 deletions failure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package caboose_test

import (
"context"
"errors"
"net/http"
"net/http/httptest"
"sync"
"testing"
"time"

"github.com/filecoin-saturn/caboose"
"github.com/stretchr/testify/require"

"github.com/filecoin-saturn/caboose"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multicodec"
)
Expand All @@ -30,8 +31,10 @@ func TestHttp429(t *testing.T) {
_, err := ch.c.Get(ctx, testCid)
require.Error(t, err)

ferr := err.(*caboose.ErrSaturnTooManyRequests)
require.EqualValues(t, expRetryAfter, ferr.RetryAfter)
var ferr *caboose.ErrSaturnTooManyRequests
ok := errors.As(err, &ferr)
require.True(t, ok)
require.EqualValues(t, expRetryAfter, ferr.RetryAfter())
}

func TestCabooseTransientFailures(t *testing.T) {
Expand Down Expand Up @@ -163,10 +166,12 @@ func (ch *CabooseHarness) runFetchesForRandCids(n int) {
func (ch *CabooseHarness) fetchAndAssertCoolDownError(t *testing.T, ctx context.Context, cid cid.Cid) {
_, err := ch.c.Get(ctx, cid)
require.Error(t, err)
coolDownErr, ok := err.(*caboose.ErrCoolDown)

var coolDownErr *caboose.ErrCoolDown
ok := errors.As(err, &coolDownErr)
require.True(t, ok)
require.EqualValues(t, cid, coolDownErr.Cid)
require.NotZero(t, coolDownErr.RetryAfter)
require.NotZero(t, coolDownErr.RetryAfter())
}

func (ch *CabooseHarness) fetchAndAssertFailure(t *testing.T, ctx context.Context, testCid cid.Cid, contains string) {
Expand Down
2 changes: 1 addition & 1 deletion fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func (p *pool) fetchResource(ctx context.Context, from string, resource string,
retryAfter = p.config.SaturnNodeCoolOff
}

return fmt.Errorf("http error from strn: %d, err=%w", resp.StatusCode, ErrSaturnTooManyRequests{RetryAfter: retryAfter, Node: from})
return fmt.Errorf("http error from strn: %d, err=%w", resp.StatusCode, &ErrSaturnTooManyRequests{retryAfter: retryAfter, Node: from})
}

// empty body so it can be re-used.
Expand Down
14 changes: 4 additions & 10 deletions pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func (p *pool) fetchBlockWith(ctx context.Context, c cid.Cid, with string) (blk
expireAt := at.(time.Time)
return nil, &ErrCoolDown{
Cid: c,
RetryAfter: time.Until(expireAt),
retryAfter: time.Until(expireAt),
}
}
p.fetchKeyLk.RUnlock()
Expand Down Expand Up @@ -426,7 +426,7 @@ func (p *pool) fetchResourceWith(ctx context.Context, path string, cb DataCallba
expireAt := at.(time.Time)
return &ErrCoolDown{
Path: path,
RetryAfter: time.Until(expireAt),
retryAfter: time.Until(expireAt),
}
}
p.fetchKeyLk.RUnlock()
Expand Down Expand Up @@ -517,14 +517,8 @@ func (p *pool) commonUpdate(node string, err error) (ferr error) {
}
}

var errTooManyRequests ErrSaturnTooManyRequests
if errors.As(err, &errTooManyRequests) {

ferr = &ErrSaturnTooManyRequests{
Node: errTooManyRequests.Node,
RetryAfter: errTooManyRequests.RetryAfter,
}

if errors.Is(err, &ErrSaturnTooManyRequests{}) {
ferr = err
if ok := p.isCoolOffLocked(node); ok {
return
}
Expand Down

0 comments on commit e621c98

Please sign in to comment.