From efd90bcd6e0926db8025108278575fb8b9003982 Mon Sep 17 00:00:00 2001 From: Constantin-Cristinel Catana Date: Sun, 6 Mar 2022 12:31:07 +0200 Subject: [PATCH] Add mechanism to list more than 100 incidents By default we can reach only 100 elements from a given range, if we have more than 100 elements between `Since` and `Until`, we need to use an offeset to get the 101st element and so on. --- incident.go | 36 ++++++++++++++++++++++++++++++++ incident_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/incident.go b/incident.go index ae5c1b27..b029c7c2 100644 --- a/incident.go +++ b/incident.go @@ -3,6 +3,7 @@ package pagerduty import ( "context" "fmt" + "net/http" "github.com/google/go-querystring/query" ) @@ -163,6 +164,10 @@ func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, return c.ListIncidentsWithContext(context.Background(), o) } +func (c *Client) ListIncidentsPaginated(o ListIncidentsOptions) ([]Incident, error) { + return c.ListIncidentsPaginatedWithContext(context.Background(), o) +} + // ListIncidentsWithContext lists existing incidents. func (c *Client) ListIncidentsWithContext(ctx context.Context, o ListIncidentsOptions) (*ListIncidentsResponse, error) { v, err := query.Values(o) @@ -183,6 +188,37 @@ func (c *Client) ListIncidentsWithContext(ctx context.Context, o ListIncidentsOp return &result, nil } +// ListIncidentsPaginated lists existing services processing paginated responses +func (c *Client) ListIncidentsPaginatedWithContext(ctx context.Context, o ListIncidentsOptions) ([]Incident, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + + var incidents []Incident + + responseHandler := func(response *http.Response) (APIListObject, error) { + var result ListIncidentsResponse + if err := c.decodeJSON(response, &result); err != nil { + return APIListObject{}, err + } + + incidents = append(incidents, result.Incidents...) + + return APIListObject{ + More: result.More, + Offset: result.Offset, + Limit: result.Limit, + }, nil + } + + if err := c.pagedGet(ctx, "/incidents?"+v.Encode(), responseHandler); err != nil { + return nil, err + } + + return incidents, nil +} + // createIncidentResponse is returned from the API when creating a response. type createIncidentResponse struct { Incident Incident `json:"incident"` diff --git a/incident_test.go b/incident_test.go index 208dcbf4..b8c49aaf 100644 --- a/incident_test.go +++ b/incident_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" "net/http" + "strconv" "testing" ) @@ -41,6 +42,59 @@ func TestIncident_List(t *testing.T) { testEqual(t, want, res) } +func TestIncident_ListPaginated(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/incidents", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + offsetStr := r.URL.Query()["offset"][0] + offset, _ := strconv.ParseInt(offsetStr, 10, 32) + + var more string + if offset == 0 { + more = "true" + } else { + more = "false" + } + resp := fmt.Sprintf(`{"incidents": [{"id": "%d"}], + "More": %s, + "Offset": %d, + "Limit": 1}`, offset, more, offset) + _, _ = w.Write([]byte(resp)) + }) + + listObj := APIListObject{Limit: 1, Offset: 0, More: false, Total: 0} + client := defaultTestClient(server.URL, "foo") + opts := ListIncidentsOptions{ + Limit: listObj.Limit, + Offset: listObj.Offset, + TeamIDs: []string{}, + TimeZone: "foo", + SortBy: "bar", + Includes: []string{}, + } + res, err := client.ListIncidentsPaginated(opts) + + want := []Incident{ + { + APIObject: APIObject{ + ID: "0", + }, + }, + { + APIObject: APIObject{ + ID: "1", + }, + }, + } + + if err != nil { + t.Fatal(err) + } + testEqual(t, want, res) +} + func TestIncident_Create(t *testing.T) { setup() defer teardown()