[golang] handle paginated requests
This commit is contained in:
parent
66466e161f
commit
3cae67aea4
1 changed files with 61 additions and 22 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +26,13 @@ func (e *APIError) Error() string {
|
||||||
type APIMessage struct {
|
type APIMessage struct {
|
||||||
Data json.RawMessage `json:"data"`
|
Data json.RawMessage `json:"data"`
|
||||||
Error *APIError `json:"error"`
|
Error *APIError `json:"error"`
|
||||||
//meta
|
Meta *Meta `json:"meta"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Meta struct {
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
Total int `json:"total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
|
@ -45,30 +52,62 @@ type Response struct {
|
||||||
|
|
||||||
func (c *Client) Send(method string, uriRef *url.URL, payload any, response any) error {
|
func (c *Client) Send(method string, uriRef *url.URL, payload any, response any) error {
|
||||||
responseChannel := make(chan *Response)
|
responseChannel := make(chan *Response)
|
||||||
c.requestsChannel <- &Request{
|
uri := c.baseURI.ResolveReference(uriRef)
|
||||||
method: method,
|
query := uri.Query()
|
||||||
payload: payload,
|
query.Add("limit", "20")
|
||||||
priority: 10,
|
page := 1
|
||||||
responseChannel: responseChannel,
|
var rawResponses []json.RawMessage
|
||||||
uri: c.baseURI.ResolveReference(uriRef),
|
for {
|
||||||
}
|
query.Set("page", strconv.Itoa(page))
|
||||||
res := <-responseChannel
|
uri.RawQuery = query.Encode()
|
||||||
if res.Err != nil {
|
c.requestsChannel <- &Request{
|
||||||
return res.Err
|
method: method,
|
||||||
}
|
payload: payload,
|
||||||
err := res.Message.Error
|
priority: 10,
|
||||||
if err != nil {
|
responseChannel: responseChannel,
|
||||||
switch err.Code {
|
uri: uri,
|
||||||
case 4214:
|
}
|
||||||
e := decodeShipInTransitError(err.Data)
|
res := <-responseChannel
|
||||||
time.Sleep(e.SecondsToArrival.Duration() * time.Second)
|
if res.Err != nil {
|
||||||
return c.Send(method, uriRef, payload, response)
|
return res.Err
|
||||||
default:
|
}
|
||||||
|
if err := res.Message.Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err := res.Message.Error
|
||||||
|
if err != nil {
|
||||||
|
switch err.Code {
|
||||||
|
case 4214:
|
||||||
|
e := decodeShipInTransitError(err.Data)
|
||||||
|
time.Sleep(e.SecondsToArrival.Duration() * time.Second)
|
||||||
|
return c.Send(method, uriRef, payload, response)
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if res.Message.Meta == nil {
|
||||||
|
// This is not a paginated request, we are done
|
||||||
|
if err := json.Unmarshal(res.Message.Data, &response); err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal message: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var oneResponse []json.RawMessage
|
||||||
|
if err := json.Unmarshal(res.Message.Data, &oneResponse); err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal message: %w", err)
|
||||||
|
}
|
||||||
|
rawResponses = append(rawResponses, oneResponse...)
|
||||||
|
if res.Message.Meta.Limit*res.Message.Meta.Page >= res.Message.Meta.Total {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
page++
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(res.Message.Data, &response); err != nil {
|
responses, err := json.Marshal(rawResponses)
|
||||||
return fmt.Errorf("failed to unmarshal message: %w", err)
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal raw responses to paginated request: %w", err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(responses, &response); err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal paginated request responses: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue