sorare/graphql/client.go

143 lines
3.1 KiB
Go
Raw Normal View History

2024-03-08 10:48:21 +00:00
package graphql
import (
"context"
"net/http"
"sync"
"time"
"github.com/llehouerou/go-graphql-client"
"github.com/pkg/errors"
"golang.org/x/time/rate"
)
const (
rateLimitPeriod = time.Second
rateLimitBurst = 60
MaxAuthenticatedQueryComplexity = 30000
MaxAnonymousQueryComplexity = 500
)
type Client struct {
httpClient *http.Client
gql *graphql.Client
rl *rate.Limiter
2024-08-03 17:36:25 +00:00
apirl *rate.Limiter
2024-03-08 10:48:21 +00:00
lock *sync.Mutex
authenticated bool
token JwtToken
2024-08-03 17:36:25 +00:00
apiKey string
2024-03-08 10:48:21 +00:00
}
func NewClient(httpclient *http.Client, baseUrl string) *Client {
return &Client{
httpClient: httpclient,
gql: graphql.NewClient(baseUrl, httpclient),
rl: rate.NewLimiter(rate.Every(rateLimitPeriod), rateLimitBurst),
2024-08-03 17:36:25 +00:00
apirl: rate.NewLimiter(rate.Every(rateLimitPeriod/10), rateLimitBurst*10),
2024-03-08 10:48:21 +00:00
lock: &sync.Mutex{},
authenticated: false,
}
}
func (c *Client) GetCurrentToken() JwtToken {
return c.token
}
func (c *Client) SetJWTToken(token JwtToken, audience string) {
c.gql = c.gql.WithRequestModifier(func(request *http.Request) {
request.Header.Set("Authorization", "Bearer "+token.Token)
request.Header.Set("JWT-AUD", audience)
})
c.token = token
c.authenticated = true
}
2024-08-03 17:36:25 +00:00
func (c *Client) SetApiKey(apiKey string) {
c.gql = c.gql.WithRequestModifier(func(request *http.Request) {
request.Header.Set("APIKEY", apiKey)
})
c.apiKey = apiKey
}
2024-03-08 10:48:21 +00:00
func (c *Client) MaxComplexity() int {
if c.authenticated {
return MaxAuthenticatedQueryComplexity
} else {
return MaxAnonymousQueryComplexity
}
}
func (c *Client) ConstructRawQuery(
q interface{},
variables map[string]interface{},
) (string, error) {
return graphql.ConstructQuery(q, variables)
}
func (c *Client) Query(
ctx context.Context,
q interface{},
variables interface{},
options ...graphql.Option,
) error {
2024-08-03 17:36:25 +00:00
if c.apiKey != "" {
err := c.apirl.Wait(ctx)
if err != nil {
return errors.Wrap(err, "waiting for rate limit")
}
} else {
err := c.rl.Wait(ctx)
if err != nil {
return errors.Wrap(err, "waiting for rate limit")
}
2024-03-08 10:48:21 +00:00
}
c.lock.Lock()
defer c.lock.Unlock()
return c.gql.Query(ctx, q, variables, options...)
}
2024-03-27 04:37:45 +00:00
func (c *Client) QueryRaw(
ctx context.Context,
q interface{},
variables interface{},
options ...graphql.Option,
) ([]byte, error) {
2024-08-03 17:36:25 +00:00
if c.apiKey != "" {
err := c.apirl.Wait(ctx)
if err != nil {
return nil, errors.Wrap(err, "waiting for rate limit")
}
} else {
err := c.rl.Wait(ctx)
if err != nil {
return nil, errors.Wrap(err, "waiting for rate limit")
}
2024-03-27 04:37:45 +00:00
}
c.lock.Lock()
defer c.lock.Unlock()
return c.gql.QueryRaw(ctx, q, variables, options...)
}
2024-03-08 10:48:21 +00:00
func (c *Client) Mutate(
ctx context.Context,
q interface{},
variables interface{},
options ...graphql.Option,
) error {
2024-08-03 17:36:25 +00:00
if c.apiKey != "" {
err := c.apirl.Wait(ctx)
if err != nil {
return errors.Wrap(err, "waiting for rate limit")
}
} else {
err := c.rl.Wait(ctx)
if err != nil {
return errors.Wrap(err, "waiting for rate limit")
}
2024-03-08 10:48:21 +00:00
}
c.lock.Lock()
defer c.lock.Unlock()
return c.gql.Mutate(ctx, q, variables, options...)
}