Skip to content

Commit 714ab17

Browse files
committed
wrap calls with exponential backoff logic to prevent issues where we get infinitely rate limited by the hetzner api
1 parent 0216581 commit 714ab17

File tree

1 file changed

+99
-9
lines changed

1 file changed

+99
-9
lines changed

driver.go

+99-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"math"
67
"os"
78
"strconv"
89
"strings"
@@ -21,7 +22,26 @@ var trueVar = true
2122
var falseVar = false
2223

2324
type hetznerDriver struct {
24-
client hetznerClienter
25+
client hetznerClienter
26+
nextTry time.Time
27+
failuresInARow int
28+
}
29+
30+
func (hd *hetznerDriver) checkBackoff() error {
31+
if time.Now().Before(hd.nextTry) {
32+
return fmt.Errorf("last failure too recent; waiting a bit before retrying")
33+
}
34+
return nil
35+
}
36+
37+
func (hd *hetznerDriver) handleBackoff(err error) {
38+
if err == nil {
39+
hd.failuresInARow = 0
40+
}
41+
if err != nil {
42+
hd.nextTry = time.Now().Add(time.Duration(int64(math.Pow(2, float64(hd.failuresInARow)))) * time.Second)
43+
hd.failuresInARow++
44+
}
2545
}
2646

2747
func newHetznerDriver() *hetznerDriver {
@@ -36,7 +56,7 @@ func (hd *hetznerDriver) Capabilities() *volume.CapabilitiesResponse {
3656
}
3757
}
3858

39-
func (hd *hetznerDriver) Create(req *volume.CreateRequest) error {
59+
func (hd *hetznerDriver) createInternal(req *volume.CreateRequest) error {
4060
validateOptions(req.Name, req.Options)
4161

4262
prefixedName := prefixName(req.Name)
@@ -61,7 +81,7 @@ func (hd *hetznerDriver) Create(req *volume.CreateRequest) error {
6181
}
6282
switch f := getOption("fstype", req.Options); f {
6383
case "xfs", "ext4":
64-
opts.Format = hcloud.String(f)
84+
opts.Format = hcloud.Ptr(f)
6585
}
6686

6787
resp, _, err := hd.client.Volume().Create(context.Background(), opts)
@@ -118,7 +138,17 @@ func (hd *hetznerDriver) Create(req *volume.CreateRequest) error {
118138
return nil
119139
}
120140

121-
func (hd *hetznerDriver) List() (*volume.ListResponse, error) {
141+
func (hd *hetznerDriver) Create(req *volume.CreateRequest) error {
142+
if err := hd.checkBackoff(); err != nil {
143+
return err
144+
}
145+
146+
err := hd.createInternal(req)
147+
hd.handleBackoff(err)
148+
return err
149+
}
150+
151+
func (hd *hetznerDriver) listInternal() (*volume.ListResponse, error) {
122152
logrus.Infof("got list request")
123153

124154
vols, err := hd.client.Volume().All(context.Background())
@@ -150,7 +180,17 @@ func (hd *hetznerDriver) List() (*volume.ListResponse, error) {
150180
return &resp, nil
151181
}
152182

153-
func (hd *hetznerDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error) {
183+
func (hd *hetznerDriver) List() (*volume.ListResponse, error) {
184+
if err := hd.checkBackoff(); err != nil {
185+
return nil, err
186+
}
187+
188+
resp, err := hd.listInternal()
189+
hd.handleBackoff(err)
190+
return resp, err
191+
}
192+
193+
func (hd *hetznerDriver) getInternal(req *volume.GetRequest) (*volume.GetResponse, error) {
154194
prefixedName := prefixName(req.Name)
155195

156196
logrus.Infof("fetching information for volume %q", prefixedName)
@@ -186,7 +226,17 @@ func (hd *hetznerDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error
186226
return &resp, nil
187227
}
188228

189-
func (hd *hetznerDriver) Remove(req *volume.RemoveRequest) error {
229+
func (hd *hetznerDriver) Get(req *volume.GetRequest) (*volume.GetResponse, error) {
230+
if err := hd.checkBackoff(); err != nil {
231+
return nil, err
232+
}
233+
234+
resp, err := hd.getInternal(req)
235+
hd.handleBackoff(err)
236+
return resp, err
237+
}
238+
239+
func (hd *hetznerDriver) removeInternal(req *volume.RemoveRequest) error {
190240
prefixedName := prefixName(req.Name)
191241

192242
logrus.Infof("starting volume removal for %q", prefixedName)
@@ -228,7 +278,17 @@ func (hd *hetznerDriver) Remove(req *volume.RemoveRequest) error {
228278
return nil
229279
}
230280

231-
func (hd *hetznerDriver) Path(req *volume.PathRequest) (*volume.PathResponse, error) {
281+
func (hd *hetznerDriver) Remove(req *volume.RemoveRequest) error {
282+
if err := hd.checkBackoff(); err != nil {
283+
return err
284+
}
285+
286+
err := hd.removeInternal(req)
287+
hd.handleBackoff(err)
288+
return err
289+
}
290+
291+
func (hd *hetznerDriver) pathInternal(req *volume.PathRequest) (*volume.PathResponse, error) {
232292
prefixedName := prefixName(req.Name)
233293

234294
logrus.Infof("got path request for volume %q", prefixedName)
@@ -241,7 +301,17 @@ func (hd *hetznerDriver) Path(req *volume.PathRequest) (*volume.PathResponse, er
241301
return &volume.PathResponse{Mountpoint: resp.Volume.Mountpoint}, nil
242302
}
243303

244-
func (hd *hetznerDriver) Mount(req *volume.MountRequest) (*volume.MountResponse, error) {
304+
func (hd *hetznerDriver) Path(req *volume.PathRequest) (*volume.PathResponse, error) {
305+
if err := hd.checkBackoff(); err != nil {
306+
return nil, err
307+
}
308+
309+
resp, err := hd.pathInternal(req)
310+
hd.handleBackoff(err)
311+
return resp, err
312+
}
313+
314+
func (hd *hetznerDriver) mountInternal(req *volume.MountRequest) (*volume.MountResponse, error) {
245315
prefixedName := prefixName(req.Name)
246316

247317
logrus.Infof("received mount request for %q as %q", prefixedName, req.ID)
@@ -313,7 +383,17 @@ func (hd *hetznerDriver) Mount(req *volume.MountRequest) (*volume.MountResponse,
313383
return &volume.MountResponse{Mountpoint: mountpoint}, nil
314384
}
315385

316-
func (hd *hetznerDriver) Unmount(req *volume.UnmountRequest) error {
386+
func (hd *hetznerDriver) Mount(req *volume.MountRequest) (*volume.MountResponse, error) {
387+
if err := hd.checkBackoff(); err != nil {
388+
return nil, err
389+
}
390+
391+
resp, err := hd.mountInternal(req)
392+
hd.handleBackoff(err)
393+
return resp, err
394+
}
395+
396+
func (hd *hetznerDriver) unmountInternal(req *volume.UnmountRequest) error {
317397
prefixedName := prefixName(req.Name)
318398

319399
logrus.Infof("received unmount request for %q as %q", prefixedName, req.ID)
@@ -357,6 +437,16 @@ func (hd *hetznerDriver) Unmount(req *volume.UnmountRequest) error {
357437
return nil
358438
}
359439

440+
func (hd *hetznerDriver) Unmount(req *volume.UnmountRequest) error {
441+
if err := hd.checkBackoff(); err != nil {
442+
return err
443+
}
444+
445+
err := hd.unmountInternal(req)
446+
hd.handleBackoff(err)
447+
return err
448+
}
449+
360450
func (hd *hetznerDriver) getServerForLocalhost() (*hcloud.Server, error) {
361451
hostname, err := os.Hostname()
362452
if err != nil {

0 commit comments

Comments
 (0)