Skip to content

Commit

Permalink
feat: use quick group in arweave client
Browse files Browse the repository at this point in the history
  • Loading branch information
pseudoyu committed Nov 27, 2023
1 parent d8a0fed commit 33ae93a
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 28 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/dmarkham/enumer v1.5.9 // indirect
github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-ole/go-ole v1.2.5 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/dmarkham/enumer v1.5.9 h1:NM/1ma/AUNieHZg74w67GkHFBNB15muOt3sj486QVZk=
github.com/dmarkham/enumer v1.5.9/go.mod h1:e4VILe2b1nYK3JKJpRmNdl5xbDQvELc6tQ8b+GsGk6E=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down Expand Up @@ -258,8 +256,6 @@ github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqky
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pascaldekloe/name v1.0.0 h1:n7LKFgHixETzxpRv2R77YgPUFo85QHGZKrdaYm7eY5U=
github.com/pascaldekloe/name v1.0.0/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
58 changes: 36 additions & 22 deletions provider/arweave/client.go → provider/arweave/client_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,60 @@ import (
"io"
"net/http"
"net/url"
"sync"

syncx "github.com/naturalselectionlabs/rss3-node/common/sync"
"github.com/samber/lo"
)

// DefaultClient is the default HTTP client.
var DefaultClient = lo.Must(NewClient())

// Client is the interface that wraps the Fetch method.
type Client interface {
type HTTPClient interface {
Fetch(ctx context.Context, id string) (io.ReadCloser, error)
}

// Ensure that client implements Client.
var _ Client = (*client)(nil)
var _ HTTPClient = (*httpClient)(nil)

// client is the default implementation of Client with Endpoints
type client struct {
type httpClient struct {
httpClient *http.Client
endpointURLs []*url.URL
locker sync.RWMutex
}

// Fetch fetches the data of the given hash from arweave network.
func (c *client) Fetch(ctx context.Context, id string) (io.ReadCloser, error) {
func (h *httpClient) Fetch(ctx context.Context, id string) (io.ReadCloser, error) {
h.locker.RLock()
defer h.locker.RUnlock()

quickGroup := syncx.NewQuickGroup[io.ReadCloser](ctx)

// try to fetch from all endpoints until we get a response (arweave gateways).
for _, endpoint := range c.endpointURLs {
response, err := c.fetch(ctx, endpoint, id)
if err == nil {
return response, nil
}
for _, endpoint := range h.endpointURLs {
endpoint := endpoint

quickGroup.Go(func(ctx context.Context) (io.ReadCloser, error) {
return h.fetch(ctx, endpoint, id)
})
}

result, err := quickGroup.Wait()
if err != nil {
return nil, fmt.Errorf("fetch from all endpoints: %w", err)
}

return nil, fmt.Errorf("failed to fetch %s", id)
return result, nil
}

// fetch fetches the data of the given hash from the given endpoint.
func (c *client) fetch(ctx context.Context, endpointURL *url.URL, id string) (io.ReadCloser, error) {
requestURL := endpointURL
requestURL.Path = id
func (h *httpClient) fetch(ctx context.Context, endpointURL *url.URL, id string) (io.ReadCloser, error) {
gatewaysURL := *endpointURL
gatewaysURL.Path = id

request, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL.String(), nil)
request, err := http.NewRequestWithContext(ctx, http.MethodGet, gatewaysURL.String(), nil)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
Expand All @@ -59,11 +73,11 @@ func (c *client) fetch(ctx context.Context, endpointURL *url.URL, id string) (io
}

// ClientOption is the type of the options passed to NewClient.
type ClientOption func(*client) error
type HTTPClientOption func(*httpClient) error

// WithEndpointURLs WithHTTPClient sets the HTTP client with arweave endpoints.
func WithEndpointURLs(endpoints []string) ClientOption {
return func(h *client) error {
func WithEndpointURLs(endpoints []string) HTTPClientOption {
return func(h *httpClient) error {
for _, endpoint := range endpoints {
endpointURL, err := url.Parse(endpoint)
if err != nil {
Expand All @@ -78,21 +92,21 @@ func WithEndpointURLs(endpoints []string) ClientOption {
}

// NewClient creates a new Client with the given options.
func NewClient(options ...ClientOption) (Client, error) {
client := client{
func NewClient(options ...HTTPClientOption) (HTTPClient, error) {
instance := httpClient{
httpClient: http.DefaultClient,
endpointURLs: make([]*url.URL, 0),
}

if err := WithEndpointURLs(EndpointStrings())(&client); err != nil {
if err := WithEndpointURLs(EndpointStrings())(&instance); err != nil {
return nil, fmt.Errorf("apply default option: %w", err)
}

for _, option := range options {
if err := option(&client); err != nil {
if err := option(&instance); err != nil {
return nil, fmt.Errorf("apply option: %w", err)
}
}

return &client, nil
return &instance, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

var (
setupOnce sync.Once
arweaveClient arweave.Client
arweaveClient arweave.HTTPClient
)

func setup(t *testing.T) {
Expand Down

0 comments on commit 33ae93a

Please sign in to comment.