Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #150 from grafana/inkel/fix-retry-missing-body
Browse files Browse the repository at this point in the history
Fix retry mechanism not sending body if first request fails before reading the body
  • Loading branch information
inkel authored May 12, 2023
2 parents 3f84a92 + 09a55c8 commit e5fb6a3
Show file tree
Hide file tree
Showing 41 changed files with 179 additions and 131 deletions.
9 changes: 4 additions & 5 deletions admin.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
)
Expand All @@ -25,7 +24,7 @@ func (c *Client) CreateUser(user User) (int64, error) {
ID int64 `json:"id"`
}{}

err = c.request("POST", "/api/admin/users", nil, bytes.NewBuffer(data), &created)
err = c.request("POST", "/api/admin/users", nil, data, &created)
if err != nil {
return id, err
}
Expand All @@ -45,7 +44,7 @@ func (c *Client) UpdateUserPassword(id int64, password string) error {
if err != nil {
return err
}
return c.request("PUT", fmt.Sprintf("/api/admin/users/%d/password", id), nil, bytes.NewBuffer(data), nil)
return c.request("PUT", fmt.Sprintf("/api/admin/users/%d/password", id), nil, data, nil)
}

// UpdateUserPermissions sets a user's admin status.
Expand All @@ -55,7 +54,7 @@ func (c *Client) UpdateUserPermissions(id int64, isAdmin bool) error {
if err != nil {
return err
}
return c.request("PUT", fmt.Sprintf("/api/admin/users/%d/permissions", id), nil, bytes.NewBuffer(data), nil)
return c.request("PUT", fmt.Sprintf("/api/admin/users/%d/permissions", id), nil, data, nil)
}

// PauseAllAlerts pauses all Grafana alerts.
Expand All @@ -68,7 +67,7 @@ func (c *Client) PauseAllAlerts() (PauseAllAlertsResponse, error) {
return result, err
}

err = c.request("POST", "/api/admin/pause-all-alerts", nil, bytes.NewBuffer(data), &result)
err = c.request("POST", "/api/admin/pause-all-alerts", nil, data, &result)

return result, err
}
3 changes: 1 addition & 2 deletions alert.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
"net/url"
Expand Down Expand Up @@ -68,7 +67,7 @@ func (c *Client) PauseAlert(id int64) (PauseAlertResponse, error) {
return result, err
}

err = c.request("POST", path, nil, bytes.NewBuffer(data), &result)
err = c.request("POST", path, nil, data, &result)
if err != nil {
return result, err
}
Expand Down
7 changes: 3 additions & 4 deletions alerting_alert_rule.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
"time"
Expand Down Expand Up @@ -93,7 +92,7 @@ func (c *Client) SetAlertRuleGroup(group RuleGroup) error {
}

uri := fmt.Sprintf("/api/v1/provisioning/folder/%s/rule-groups/%s", folderUID, name)
return c.request("PUT", uri, nil, bytes.NewBuffer(req), nil)
return c.request("PUT", uri, nil, req, nil)
}

// NewAlertRule creates a new alert rule and returns its UID.
Expand All @@ -104,7 +103,7 @@ func (c *Client) NewAlertRule(ar *AlertRule) (string, error) {
return "", err
}
result := AlertRule{}
err = c.request("POST", "/api/v1/provisioning/alert-rules", nil, bytes.NewBuffer(req), &result)
err = c.request("POST", "/api/v1/provisioning/alert-rules", nil, req, &result)
if err != nil {
return "", err
}
Expand All @@ -120,7 +119,7 @@ func (c *Client) UpdateAlertRule(ar *AlertRule) error {
return err
}

return c.request("PUT", uri, nil, bytes.NewBuffer(req), nil)
return c.request("PUT", uri, nil, req, nil)
}

// DeleteAlertRule deletes a alert rule, identified by the alert rule's UID.
Expand Down
5 changes: 2 additions & 3 deletions alerting_contact_point.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
"net/url"
Expand Down Expand Up @@ -62,7 +61,7 @@ func (c *Client) NewContactPoint(p *ContactPoint) (string, error) {
}
result := ContactPoint{}

err = c.request("POST", "/api/v1/provisioning/contact-points", nil, bytes.NewBuffer(req), &result)
err = c.request("POST", "/api/v1/provisioning/contact-points", nil, req, &result)
if err != nil {
return "", err
}
Expand All @@ -77,7 +76,7 @@ func (c *Client) UpdateContactPoint(p *ContactPoint) error {
return err
}

return c.request("PUT", uri, nil, bytes.NewBuffer(req), nil)
return c.request("PUT", uri, nil, req, nil)
}

// DeleteContactPoint deletes a contact point.
Expand Down
3 changes: 1 addition & 2 deletions alerting_message_template.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
)
Expand Down Expand Up @@ -44,7 +43,7 @@ func (c *Client) SetMessageTemplate(name, content string) error {
}

uri := fmt.Sprintf("/api/v1/provisioning/templates/%s", name)
return c.request("PUT", uri, nil, bytes.NewBuffer(body), nil)
return c.request("PUT", uri, nil, body, nil)
}

// DeleteMessageTemplate deletes a message template.
Expand Down
5 changes: 2 additions & 3 deletions alerting_mute_timing.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
)
Expand Down Expand Up @@ -65,7 +64,7 @@ func (c *Client) NewMuteTiming(mt *MuteTiming) error {
return err
}

return c.request("POST", "/api/v1/provisioning/mute-timings", nil, bytes.NewBuffer(req), nil)
return c.request("POST", "/api/v1/provisioning/mute-timings", nil, req, nil)
}

// UpdateMuteTiming updates a mute timing.
Expand All @@ -76,7 +75,7 @@ func (c *Client) UpdateMuteTiming(mt *MuteTiming) error {
return err
}

return c.request("PUT", uri, nil, bytes.NewBuffer(req), nil)
return c.request("PUT", uri, nil, req, nil)
}

// DeleteMutetiming deletes a mute timing.
Expand Down
3 changes: 1 addition & 2 deletions alerting_notification_policy.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
)
Expand Down Expand Up @@ -116,7 +115,7 @@ func (c *Client) SetNotificationPolicyTree(np *NotificationPolicyTree) error {
if err != nil {
return err
}
return c.request("PUT", "/api/v1/provisioning/policies", nil, bytes.NewBuffer(req), nil)
return c.request("PUT", "/api/v1/provisioning/policies", nil, req, nil)
}

func (c *Client) ResetNotificationPolicyTree() error {
Expand Down
5 changes: 2 additions & 3 deletions alertnotification.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
)
Expand Down Expand Up @@ -59,7 +58,7 @@ func (c *Client) NewAlertNotification(a *AlertNotification) (int64, error) {
ID int64 `json:"id"`
}{}

err = c.request("POST", "/api/alert-notifications", nil, bytes.NewBuffer(data), &result)
err = c.request("POST", "/api/alert-notifications", nil, data, &result)
if err != nil {
return 0, err
}
Expand All @@ -75,7 +74,7 @@ func (c *Client) UpdateAlertNotification(a *AlertNotification) error {
if err != nil {
return err
}
err = c.request("PUT", path, nil, bytes.NewBuffer(data), nil)
err = c.request("PUT", path, nil, data, nil)

return err
}
Expand Down
13 changes: 6 additions & 7 deletions annotation.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
"net/url"
Expand Down Expand Up @@ -58,7 +57,7 @@ func (c *Client) NewAnnotation(a *Annotation) (int64, error) {
ID int64 `json:"id"`
}{}

err = c.request("POST", "/api/annotations", nil, bytes.NewBuffer(data), &result)
err = c.request("POST", "/api/annotations", nil, data, &result)
if err != nil {
return 0, err
}
Expand All @@ -77,7 +76,7 @@ func (c *Client) NewGraphiteAnnotation(gfa *GraphiteAnnotation) (int64, error) {
ID int64 `json:"id"`
}{}

err = c.request("POST", "/api/annotations/graphite", nil, bytes.NewBuffer(data), &result)
err = c.request("POST", "/api/annotations/graphite", nil, data, &result)
if err != nil {
return 0, err
}
Expand All @@ -97,7 +96,7 @@ func (c *Client) UpdateAnnotation(id int64, a *Annotation) (string, error) {
Message string `json:"message"`
}{}

err = c.request("PUT", path, nil, bytes.NewBuffer(data), &result)
err = c.request("PUT", path, nil, data, &result)
if err != nil {
return "", err
}
Expand All @@ -117,7 +116,7 @@ func (c *Client) PatchAnnotation(id int64, a *Annotation) (string, error) {
Message string `json:"message"`
}{}

err = c.request("PATCH", path, nil, bytes.NewBuffer(data), &result)
err = c.request("PATCH", path, nil, data, &result)
if err != nil {
return "", err
}
Expand All @@ -132,7 +131,7 @@ func (c *Client) DeleteAnnotation(id int64) (string, error) {
Message string `json:"message"`
}{}

err := c.request("DELETE", path, nil, bytes.NewBuffer(nil), &result)
err := c.request("DELETE", path, nil, nil, &result)
if err != nil {
return "", err
}
Expand All @@ -147,7 +146,7 @@ func (c *Client) DeleteAnnotationByRegionID(id int64) (string, error) {
Message string `json:"message"`
}{}

err := c.request("DELETE", path, nil, bytes.NewBuffer(nil), &result)
err := c.request("DELETE", path, nil, nil, &result)
if err != nil {
return "", err
}
Expand Down
3 changes: 1 addition & 2 deletions api_key.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
"net/url"
Expand Down Expand Up @@ -42,7 +41,7 @@ func (c *Client) CreateAPIKey(request CreateAPIKeyRequest) (CreateAPIKeyResponse
return response, err
}

err = c.request("POST", "/api/auth/keys", nil, bytes.NewBuffer(data), &response)
err = c.request("POST", "/api/auth/keys", nil, data, &response)
return response, err
}

Expand Down
5 changes: 2 additions & 3 deletions builtin_role_assignments.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gapi

import (
"bytes"
"encoding/json"
"fmt"
)
Expand Down Expand Up @@ -33,7 +32,7 @@ func (c *Client) NewBuiltInRoleAssignment(builtInRoleAssignment BuiltInRoleAssig

br := &BuiltInRoleAssignment{}

err = c.request("POST", baseURL, nil, bytes.NewBuffer(body), &br)
err = c.request("POST", baseURL, nil, body, &br)
if err != nil {
return nil, err
}
Expand All @@ -52,7 +51,7 @@ func (c *Client) DeleteBuiltInRoleAssignment(builtInRole BuiltInRoleAssignment)
"global": {fmt.Sprint(builtInRole.Global)},
}
url := fmt.Sprintf("%s/%s/roles/%s", baseURL, builtInRole.BuiltinRole, builtInRole.RoleUID)
err = c.request("DELETE", url, qp, bytes.NewBuffer(data), nil)
err = c.request("DELETE", url, qp, data, nil)

return err
}
22 changes: 8 additions & 14 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ type Config struct {
OrgID int64
// NumRetries contains the number of attempted retries
NumRetries int
// RetryTimeout says how long to wait before retrying a request
RetryTimeout time.Duration
}

// New creates a new Grafana client.
Expand Down Expand Up @@ -71,35 +73,27 @@ func (c Client) WithOrgID(orgID int64) *Client {
return &c
}

func (c *Client) request(method, requestPath string, query url.Values, body io.Reader, responseStruct interface{}) error {
func (c *Client) request(method, requestPath string, query url.Values, body []byte, responseStruct interface{}) error {
var (
req *http.Request
resp *http.Response
err error
bodyContents []byte
)

// If we want to retry a request that sends data, we'll need to stash the request data in memory. Otherwise, we lose it since readers cannot be replayed.
var bodyBuffer bytes.Buffer
if c.config.NumRetries > 0 && body != nil {
body = io.TeeReader(body, &bodyBuffer)
}

// retry logic
for n := 0; n <= c.config.NumRetries; n++ {
// If it's not the first request, re-use the request body we stashed earlier.
if n > 0 {
body = bytes.NewReader(bodyBuffer.Bytes())
}

req, err = c.newRequest(method, requestPath, query, body)
req, err = c.newRequest(method, requestPath, query, bytes.NewReader(body))
if err != nil {
return err
}

// Wait a bit if that's not the first request
if n != 0 {
time.Sleep(time.Second * 5)
if c.config.RetryTimeout == 0 {
c.config.RetryTimeout = time.Second * 5
}
time.Sleep(c.config.RetryTimeout)
}

resp, err = c.client.Do(req)
Expand Down
Loading

0 comments on commit e5fb6a3

Please sign in to comment.