1
0
Fork 0

[golang] handle paginated requests

This commit is contained in:
Julien Dessaux 2025-02-16 10:00:10 +01:00
parent 66466e161f
commit 3cae67aea4
Signed by: adyxax
GPG key ID: F92E51B86E07177E

View file

@ -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,17 +52,28 @@ 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)
uri := c.baseURI.ResolveReference(uriRef)
query := uri.Query()
query.Add("limit", "20")
page := 1
var rawResponses []json.RawMessage
for {
query.Set("page", strconv.Itoa(page))
uri.RawQuery = query.Encode()
c.requestsChannel <- &Request{ c.requestsChannel <- &Request{
method: method, method: method,
payload: payload, payload: payload,
priority: 10, priority: 10,
responseChannel: responseChannel, responseChannel: responseChannel,
uri: c.baseURI.ResolveReference(uriRef), uri: uri,
} }
res := <-responseChannel res := <-responseChannel
if res.Err != nil { if res.Err != nil {
return res.Err return res.Err
} }
if err := res.Message.Error; err != nil {
return err
}
err := res.Message.Error err := res.Message.Error
if err != nil { if err != nil {
switch err.Code { switch err.Code {
@ -67,11 +85,32 @@ func (c *Client) Send(method string, uriRef *url.URL, payload any, response any)
return err 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 { if err := json.Unmarshal(res.Message.Data, &response); err != nil {
return fmt.Errorf("failed to unmarshal message: %w", err) return fmt.Errorf("failed to unmarshal message: %w", err)
} }
return nil 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++
}
responses, err := json.Marshal(rawResponses)
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
}
func queueProcessor(client *Client) { func queueProcessor(client *Client) {
var ( var (