Skip to content

Commit deda894

Browse files
Merge pull request #289 from linode/fix/cache-include-opts
fix: Include ListOptions as part of cached endpoint keys
2 parents b413d07 + 91fba47 commit deda894

File tree

9 files changed

+283
-266
lines changed

9 files changed

+283
-266
lines changed

client.go

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,9 @@ func (c *Client) addRetryConditional(retryConditional RetryConditional) *Client
207207
return c
208208
}
209209

210-
func (c *Client) addCachedResponse(endpoint string, response any, expiry *time.Duration) error {
210+
func (c *Client) addCachedResponse(endpoint string, response any, expiry *time.Duration) {
211211
if !c.shouldCache {
212-
return nil
213-
}
214-
215-
u, err := url.Parse(endpoint)
216-
if err != nil {
217-
return fmt.Errorf("failed to parse URL for caching: %s", err)
212+
return
218213
}
219214

220215
responseValue := reflect.ValueOf(response)
@@ -236,19 +231,12 @@ func (c *Client) addCachedResponse(endpoint string, response any, expiry *time.D
236231
c.cachedEntryLock.Lock()
237232
defer c.cachedEntryLock.Unlock()
238233

239-
c.cachedEntries[u.Path] = entry
240-
241-
return nil
234+
c.cachedEntries[endpoint] = entry
242235
}
243236

244-
func (c *Client) getCachedResponse(endpoint string) (any, error) {
237+
func (c *Client) getCachedResponse(endpoint string) any {
245238
if !c.shouldCache {
246-
return nil, nil
247-
}
248-
249-
u, err := url.Parse(endpoint)
250-
if err != nil {
251-
return nil, fmt.Errorf("failed to parse URL for caching: %s", err)
239+
return nil
252240
}
253241

254242
c.cachedEntryLock.RLock()
@@ -265,9 +253,9 @@ func (c *Client) getCachedResponse(endpoint string) (any, error) {
265253
}
266254
}()
267255

268-
entry, ok := c.cachedEntries[u.Path]
256+
entry, ok := c.cachedEntries[endpoint]
269257
if !ok {
270-
return nil, nil
258+
return nil
271259
}
272260

273261
// Handle expired entries
@@ -286,11 +274,11 @@ func (c *Client) getCachedResponse(endpoint string) (any, error) {
286274
c.cachedEntryLock.Lock()
287275
defer c.cachedEntryLock.Unlock()
288276

289-
delete(c.cachedEntries, u.Path)
290-
return nil, nil
277+
delete(c.cachedEntries, endpoint)
278+
return nil
291279
}
292280

293-
return c.cachedEntries[u.Path].Data, nil
281+
return c.cachedEntries[endpoint].Data
294282
}
295283

296284
// InvalidateCache clears all cached responses for all endpoints.
@@ -523,3 +511,16 @@ func copyTime(tPtr *time.Time) *time.Time {
523511

524512
return &t
525513
}
514+
515+
func generateListCacheURL(endpoint string, opts *ListOptions) (string, error) {
516+
if opts == nil {
517+
return "", nil
518+
}
519+
520+
hashedOpts, err := opts.Hash()
521+
if err != nil {
522+
return "", err
523+
}
524+
525+
return fmt.Sprintf("%s:%s", endpoint, hashedOpts), nil
526+
}

databases.go

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -216,20 +216,21 @@ func (c *Client) ListDatabases(ctx context.Context, opts *ListOptions) ([]Databa
216216
func (c *Client) ListDatabaseEngines(ctx context.Context, opts *ListOptions) ([]DatabaseEngine, error) {
217217
response := DatabaseEnginesPagedResponse{}
218218

219-
if result, err := c.getCachedResponse(response.endpoint()); err != nil {
219+
endpoint, err := generateListCacheURL(response.endpoint(), opts)
220+
if err != nil {
220221
return nil, err
221-
} else if result != nil {
222+
}
223+
224+
if result := c.getCachedResponse(endpoint); result != nil {
222225
return result.([]DatabaseEngine), nil
223226
}
224227

225-
err := c.listHelper(ctx, &response, opts)
228+
err = c.listHelper(ctx, &response, opts)
226229
if err != nil {
227230
return nil, err
228231
}
229232

230-
if err := c.addCachedResponse(response.endpoint(), response.Data, &cacheExpiryTime); err != nil {
231-
return nil, err
232-
}
233+
c.addCachedResponse(endpoint, response.Data, &cacheExpiryTime)
233234

234235
return response.Data, nil
235236
}
@@ -238,9 +239,7 @@ func (c *Client) ListDatabaseEngines(ctx context.Context, opts *ListOptions) ([]
238239
func (c *Client) GetDatabaseEngine(ctx context.Context, opts *ListOptions, engineID string) (*DatabaseEngine, error) {
239240
e := fmt.Sprintf("databases/engines/%s", engineID)
240241

241-
if result, err := c.getCachedResponse(e); err != nil {
242-
return nil, err
243-
} else if result != nil {
242+
if result := c.getCachedResponse(e); result != nil {
244243
result := result.(DatabaseEngine)
245244
return &result, nil
246245
}
@@ -251,9 +250,7 @@ func (c *Client) GetDatabaseEngine(ctx context.Context, opts *ListOptions, engin
251250
return nil, err
252251
}
253252

254-
if err := c.addCachedResponse(e, r.Result(), &cacheExpiryTime); err != nil {
255-
return nil, err
256-
}
253+
c.addCachedResponse(e, r.Result(), &cacheExpiryTime)
257254

258255
return r.Result().(*DatabaseEngine), nil
259256
}
@@ -262,20 +259,21 @@ func (c *Client) GetDatabaseEngine(ctx context.Context, opts *ListOptions, engin
262259
func (c *Client) ListDatabaseTypes(ctx context.Context, opts *ListOptions) ([]DatabaseType, error) {
263260
response := DatabaseTypesPagedResponse{}
264261

265-
if result, err := c.getCachedResponse(response.endpoint()); err != nil {
262+
endpoint, err := generateListCacheURL(response.endpoint(), opts)
263+
if err != nil {
266264
return nil, err
267-
} else if result != nil {
265+
}
266+
267+
if result := c.getCachedResponse(endpoint); result != nil {
268268
return result.([]DatabaseType), nil
269269
}
270270

271-
err := c.listHelper(ctx, &response, opts)
271+
err = c.listHelper(ctx, &response, opts)
272272
if err != nil {
273273
return nil, err
274274
}
275275

276-
if err := c.addCachedResponse(response.endpoint(), response.Data, &cacheExpiryTime); err != nil {
277-
return nil, err
278-
}
276+
c.addCachedResponse(endpoint, response.Data, &cacheExpiryTime)
279277

280278
return response.Data, nil
281279
}
@@ -284,9 +282,7 @@ func (c *Client) ListDatabaseTypes(ctx context.Context, opts *ListOptions) ([]Da
284282
func (c *Client) GetDatabaseType(ctx context.Context, opts *ListOptions, typeID string) (*DatabaseType, error) {
285283
e := fmt.Sprintf("databases/types/%s", typeID)
286284

287-
if result, err := c.getCachedResponse(e); err != nil {
288-
return nil, err
289-
} else if result != nil {
285+
if result := c.getCachedResponse(e); result != nil {
290286
result := result.(DatabaseType)
291287
return &result, nil
292288
}
@@ -297,9 +293,7 @@ func (c *Client) GetDatabaseType(ctx context.Context, opts *ListOptions, typeID
297293
return nil, err
298294
}
299295

300-
if err := c.addCachedResponse(e, r.Result(), &cacheExpiryTime); err != nil {
301-
return nil, err
302-
}
296+
c.addCachedResponse(e, r.Result(), &cacheExpiryTime)
303297

304298
return r.Result().(*DatabaseType), nil
305299
}

kernels.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,21 @@ func (resp *LinodeKernelsPagedResponse) castResult(r *resty.Request, e string) (
4343
func (c *Client) ListKernels(ctx context.Context, opts *ListOptions) ([]LinodeKernel, error) {
4444
response := LinodeKernelsPagedResponse{}
4545

46-
if result, err := c.getCachedResponse(response.endpoint()); err != nil {
46+
endpoint, err := generateListCacheURL(response.endpoint(), opts)
47+
if err != nil {
4748
return nil, err
48-
} else if result != nil {
49+
}
50+
51+
if result := c.getCachedResponse(endpoint); result != nil {
4952
return result.([]LinodeKernel), nil
5053
}
5154

52-
err := c.listHelper(ctx, &response, opts)
55+
err = c.listHelper(ctx, &response, opts)
5356
if err != nil {
5457
return nil, err
5558
}
5659

57-
if err := c.addCachedResponse(response.endpoint(), response.Data, nil); err != nil {
58-
return nil, err
59-
}
60+
c.addCachedResponse(endpoint, response.Data, nil)
6061

6162
return response.Data, nil
6263
}
@@ -65,9 +66,7 @@ func (c *Client) ListKernels(ctx context.Context, opts *ListOptions) ([]LinodeKe
6566
func (c *Client) GetKernel(ctx context.Context, kernelID string) (*LinodeKernel, error) {
6667
e := fmt.Sprintf("linode/kernels/%s", kernelID)
6768

68-
if result, err := c.getCachedResponse(e); err != nil {
69-
return nil, err
70-
} else if result != nil {
69+
if result := c.getCachedResponse(e); result != nil {
7170
result := result.(LinodeKernel)
7271
return &result, nil
7372
}
@@ -78,9 +77,7 @@ func (c *Client) GetKernel(ctx context.Context, kernelID string) (*LinodeKernel,
7877
return nil, err
7978
}
8079

81-
if err := c.addCachedResponse(e, r.Result(), nil); err != nil {
82-
return nil, err
83-
}
80+
c.addCachedResponse(e, r.Result(), nil)
8481

8582
return r.Result().(*LinodeKernel), nil
8683
}

lke_clusters.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,21 @@ func (resp *LKEVersionsPagedResponse) castResult(r *resty.Request, e string) (in
142142
func (c *Client) ListLKEVersions(ctx context.Context, opts *ListOptions) ([]LKEVersion, error) {
143143
response := LKEVersionsPagedResponse{}
144144

145-
if result, err := c.getCachedResponse(response.endpoint()); err != nil {
145+
endpoint, err := generateListCacheURL(response.endpoint(), opts)
146+
if err != nil {
146147
return nil, err
147-
} else if result != nil {
148+
}
149+
150+
if result := c.getCachedResponse(endpoint); result != nil {
148151
return result.([]LKEVersion), nil
149152
}
150153

151-
err := c.listHelper(ctx, &response, opts)
154+
err = c.listHelper(ctx, &response, opts)
152155
if err != nil {
153156
return nil, err
154157
}
155158

156-
if err := c.addCachedResponse(response.endpoint(), response.Data, &cacheExpiryTime); err != nil {
157-
return nil, err
158-
}
159+
c.addCachedResponse(endpoint, response.Data, &cacheExpiryTime)
159160

160161
return response.Data, nil
161162
}
@@ -164,9 +165,7 @@ func (c *Client) ListLKEVersions(ctx context.Context, opts *ListOptions) ([]LKEV
164165
func (c *Client) GetLKEVersion(ctx context.Context, version string) (*LKEVersion, error) {
165166
e := fmt.Sprintf("lke/versions/%s", version)
166167

167-
if result, err := c.getCachedResponse(e); err != nil {
168-
return nil, err
169-
} else if result != nil {
168+
if result := c.getCachedResponse(e); result != nil {
170169
result := result.(LKEVersion)
171170
return &result, nil
172171
}
@@ -177,9 +176,7 @@ func (c *Client) GetLKEVersion(ctx context.Context, version string) (*LKEVersion
177176
return nil, err
178177
}
179178

180-
if err := c.addCachedResponse(e, r.Result(), &cacheExpiryTime); err != nil {
181-
return nil, err
182-
}
179+
c.addCachedResponse(e, r.Result(), &cacheExpiryTime)
183180

184181
return r.Result().(*LKEVersion), nil
185182
}

pagination.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ package linodego
66

77
import (
88
"context"
9+
"crypto/sha256"
10+
"encoding/json"
11+
"fmt"
912
"strconv"
1013

1114
"github.com/go-resty/resty/v2"
@@ -31,6 +34,19 @@ func NewListOptions(page int, filter string) *ListOptions {
3134
return &ListOptions{PageOptions: &PageOptions{Page: page}, Filter: filter}
3235
}
3336

37+
// Hash returns the sha256 hash of the provided ListOptions.
38+
// This is necessary for caching purposes.
39+
func (l ListOptions) Hash() (string, error) {
40+
data, err := json.Marshal(l)
41+
if err != nil {
42+
return "", fmt.Errorf("failed to cache ListOptions: %s", err)
43+
}
44+
45+
h := sha256.New()
46+
47+
return string(h.Sum(data)), nil
48+
}
49+
3450
func applyListOptionsToRequest(opts *ListOptions, req *resty.Request) {
3551
if opts != nil {
3652
if opts.PageOptions != nil && opts.Page > 0 {

regions.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,21 @@ func (resp *RegionsPagedResponse) castResult(r *resty.Request, e string) (int, i
5252
func (c *Client) ListRegions(ctx context.Context, opts *ListOptions) ([]Region, error) {
5353
response := RegionsPagedResponse{}
5454

55-
if result, err := c.getCachedResponse(response.endpoint()); err != nil {
55+
endpoint, err := generateListCacheURL(response.endpoint(), opts)
56+
if err != nil {
5657
return nil, err
57-
} else if result != nil {
58+
}
59+
60+
if result := c.getCachedResponse(endpoint); result != nil {
5861
return result.([]Region), nil
5962
}
6063

61-
err := c.listHelper(ctx, &response, opts)
64+
err = c.listHelper(ctx, &response, opts)
6265
if err != nil {
6366
return nil, err
6467
}
6568

66-
if err := c.addCachedResponse(response.endpoint(), response.Data, &cacheExpiryTime); err != nil {
67-
return nil, err
68-
}
69+
c.addCachedResponse(endpoint, response.Data, &cacheExpiryTime)
6970

7071
return response.Data, nil
7172
}
@@ -74,9 +75,7 @@ func (c *Client) ListRegions(ctx context.Context, opts *ListOptions) ([]Region,
7475
func (c *Client) GetRegion(ctx context.Context, regionID string) (*Region, error) {
7576
e := fmt.Sprintf("regions/%s", regionID)
7677

77-
if result, err := c.getCachedResponse(e); err != nil {
78-
return nil, err
79-
} else if result != nil {
78+
if result := c.getCachedResponse(e); result != nil {
8079
result := result.(Region)
8180
return &result, nil
8281
}
@@ -87,9 +86,7 @@ func (c *Client) GetRegion(ctx context.Context, regionID string) (*Region, error
8786
return nil, err
8887
}
8988

90-
if err := c.addCachedResponse(e, r.Result(), &cacheExpiryTime); err != nil {
91-
return nil, err
92-
}
89+
c.addCachedResponse(e, r.Result(), &cacheExpiryTime)
9390

9491
return r.Result().(*Region), nil
9592
}

0 commit comments

Comments
 (0)