Skip to content

Commit aa342df

Browse files
author
Nick Randall
committed
start of v3
1 parent f7a9a10 commit aa342df

File tree

9 files changed

+145
-44
lines changed

9 files changed

+145
-44
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vendor/

Gopkg.lock

Lines changed: 33 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
# Gopkg.toml example
3+
#
4+
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
5+
# for detailed Gopkg.toml documentation.
6+
#
7+
# required = ["github.com/user/thing/cmd/thing"]
8+
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
9+
#
10+
# [[constraint]]
11+
# name = "github.com/user/project"
12+
# version = "1.0.0"
13+
#
14+
# [[constraint]]
15+
# name = "github.com/user/project2"
16+
# branch = "dev"
17+
# source = "github.com/myfork/project2"
18+
#
19+
# [[override]]
20+
# name = "github.com/x/y"
21+
# version = "2.4.0"
22+
23+
24+
[[constraint]]
25+
branch = "master"
26+
name = "github.com/hashicorp/golang-lru"
27+
28+
[[constraint]]
29+
name = "github.com/opentracing/opentracing-go"
30+
version = "1.0.2"
31+
32+
[[constraint]]
33+
name = "github.com/patrickmn/go-cache"
34+
version = "2.1.0"

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ if err != nil {
4040
log.Printf("value: %#v", result)
4141
```
4242

43-
## Upgrade from v1
43+
## Upgrade from v1 to v2
4444
The only difference between v1 and v2 is that we added use of [context](https://golang.org/pkg/context).
4545

4646
```diff
@@ -55,6 +55,29 @@ The only difference between v1 and v2 is that we added use of [context](https://
5555
+ type BatchFunc func(context.Context, []string) []*Result
5656
```
5757

58+
## Upgrade from v2 to v3
59+
```diff
60+
// dataloader.Interface as added context.Context to methods
61+
- loader.Prime(key string, value interface{}) Interface
62+
+ loader.Prime(ctx context.Context, key string, value interface{}) Interface
63+
- loader.Clear(key string) Interface
64+
+ loader.Clear(ctx context.Context, key string) Interface
65+
```
66+
67+
```diff
68+
// cache interface as added context.Context to methods
69+
type Cache interface {
70+
- Get(string) (Thunk, bool)
71+
+ Get(context.Context, string) (Thunk, bool)
72+
- Set(string, Thunk)
73+
+ Set(context.Context, string, Thunk)
74+
- Delete(string) bool
75+
+ Delete(context.Context, string) bool
76+
Clear()
77+
}
78+
```
79+
80+
5881
### Don't need/want to use context?
5982
You're welcome to install the v1 version of this library.
6083

cache.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package dataloader
22

3+
import "context"
4+
35
// The Cache interface. If a custom cache is provided, it must implement this interface.
46
type Cache interface {
5-
Get(string) (Thunk, bool)
6-
Set(string, Thunk)
7-
Delete(string) bool
7+
Get(context.Context, string) (Thunk, bool)
8+
Set(context.Context, string, Thunk)
9+
Delete(context.Context, string) bool
810
Clear()
911
}
1012

@@ -14,13 +16,13 @@ type Cache interface {
1416
type NoCache struct{}
1517

1618
// Get is a NOOP
17-
func (c *NoCache) Get(string) (Thunk, bool) { return nil, false }
19+
func (c *NoCache) Get(context.Context, string) (Thunk, bool) { return nil, false }
1820

1921
// Set is a NOOP
20-
func (c *NoCache) Set(string, Thunk) { return }
22+
func (c *NoCache) Set(context.Context, string, Thunk) { return }
2123

2224
// Delete is a NOOP
23-
func (c *NoCache) Delete(string) bool { return false }
25+
func (c *NoCache) Delete(context.Context, string) bool { return false }
2426

2527
// Clear is a NOOP
2628
func (c *NoCache) Clear() { return }

dataloader.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import (
2222
type Interface interface {
2323
Load(context.Context, string) Thunk
2424
LoadMany(context.Context, []string) ThunkMany
25-
Clear(string) Interface
25+
Clear(context.Context, string) Interface
2626
ClearAll() Interface
27-
Prime(key string, value interface{}) Interface
27+
Prime(ctx context.Context, key string, value interface{}) Interface
2828
}
2929

3030
// BatchFunc is a function, which when given a slice of keys (string), returns an slice of `results`.
@@ -193,6 +193,7 @@ func NewBatchedLoader(batchFn BatchFunc, opts ...Option) *Loader {
193193
// Load load/resolves the given key, returning a channel that will contain the value and error
194194
func (l *Loader) Load(originalContext context.Context, key string) Thunk {
195195
ctx, finish := l.tracer.TraceLoad(originalContext, key)
196+
196197
c := make(chan *Result, 1)
197198
var result struct {
198199
mu sync.RWMutex
@@ -201,7 +202,7 @@ func (l *Loader) Load(originalContext context.Context, key string) Thunk {
201202

202203
// lock to prevent duplicate keys coming in before item has been added to cache.
203204
l.cacheLock.Lock()
204-
if v, ok := l.cache.Get(key); ok {
205+
if v, ok := l.cache.Get(ctx, key); ok {
205206
defer finish(v)
206207
defer l.cacheLock.Unlock()
207208
return v
@@ -223,8 +224,9 @@ func (l *Loader) Load(originalContext context.Context, key string) Thunk {
223224
defer result.mu.RUnlock()
224225
return result.value.Data, result.value.Error
225226
}
227+
defer finish(thunk)
226228

227-
l.cache.Set(key, thunk)
229+
l.cache.Set(ctx, key, thunk)
228230
l.cacheLock.Unlock()
229231

230232
// this is sent to batch fn. It contains the key and the channel to return the
@@ -236,7 +238,7 @@ func (l *Loader) Load(originalContext context.Context, key string) Thunk {
236238
if l.curBatcher == nil {
237239
l.curBatcher = l.newBatcher(l.silent, l.tracer)
238240
// start the current batcher batch function
239-
go l.curBatcher.batch(ctx)
241+
go l.curBatcher.batch(originalContext)
240242
// start a sleeper for the current batcher
241243
l.endSleeper = make(chan bool)
242244
go l.sleeper(l.curBatcher, l.endSleeper)
@@ -261,13 +263,13 @@ func (l *Loader) Load(originalContext context.Context, key string) Thunk {
261263
}
262264
l.batchLock.Unlock()
263265

264-
defer finish(thunk)
265266
return thunk
266267
}
267268

268269
// LoadMany loads mulitiple keys, returning a thunk (type: ThunkMany) that will resolve the keys passed in.
269270
func (l *Loader) LoadMany(originalContext context.Context, keys []string) ThunkMany {
270271
ctx, finish := l.tracer.TraceLoadMany(originalContext, keys)
272+
271273
length := len(keys)
272274
data := make([]interface{}, length)
273275
errors := make([]error, length)
@@ -276,13 +278,13 @@ func (l *Loader) LoadMany(originalContext context.Context, keys []string) ThunkM
276278

277279
wg.Add(length)
278280
for i := range keys {
279-
go func(i int) {
281+
go func(ctx context.Context, i int) {
280282
defer wg.Done()
281283
thunk := l.Load(ctx, keys[i])
282284
result, err := thunk()
283285
data[i] = result
284286
errors[i] = err
285-
}(i)
287+
}(ctx, i)
286288
}
287289

288290
go func() {
@@ -318,9 +320,9 @@ func (l *Loader) LoadMany(originalContext context.Context, keys []string) ThunkM
318320
}
319321

320322
// Clear clears the value at `key` from the cache, it it exsits. Returs self for method chaining
321-
func (l *Loader) Clear(key string) Interface {
323+
func (l *Loader) Clear(ctx context.Context, key string) Interface {
322324
l.cacheLock.Lock()
323-
l.cache.Delete(key)
325+
l.cache.Delete(ctx, key)
324326
l.cacheLock.Unlock()
325327
return l
326328
}
@@ -336,12 +338,12 @@ func (l *Loader) ClearAll() Interface {
336338

337339
// Prime adds the provided key and value to the cache. If the key already exists, no change is made.
338340
// Returns self for method chaining
339-
func (l *Loader) Prime(key string, value interface{}) Interface {
340-
if _, ok := l.cache.Get(key); !ok {
341+
func (l *Loader) Prime(ctx context.Context, key string, value interface{}) Interface {
342+
if _, ok := l.cache.Get(ctx, key); !ok {
341343
thunk := func() (interface{}, error) {
342344
return value, nil
343345
}
344-
l.cache.Set(key, thunk)
346+
l.cache.Set(ctx, key, thunk)
345347
}
346348
return l
347349
}

dataloader_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ func TestLoader(t *testing.T) {
250250
t.Run("allows primed cache", func(t *testing.T) {
251251
t.Parallel()
252252
identityLoader, loadCalls := IDLoader(0)
253-
identityLoader.Prime("A", "Cached")
254253
ctx := context.Background()
254+
identityLoader.Prime(ctx, "A", "Cached")
255255
future1 := identityLoader.Load(ctx, "1")
256256
future2 := identityLoader.Load(ctx, "A")
257257

@@ -280,10 +280,10 @@ func TestLoader(t *testing.T) {
280280
t.Parallel()
281281
identityLoader, loadCalls := IDLoader(0)
282282
ctx := context.Background()
283-
identityLoader.Prime("A", "Cached")
284-
identityLoader.Prime("B", "B")
283+
identityLoader.Prime(ctx, "A", "Cached")
284+
identityLoader.Prime(ctx, "B", "B")
285285
future1 := identityLoader.Load(ctx, "1")
286-
future2 := identityLoader.Clear("A").Load(ctx, "A")
286+
future2 := identityLoader.Clear(ctx, "A").Load(ctx, "A")
287287
future3 := identityLoader.Load(ctx, "B")
288288

289289
_, err := future1()
@@ -334,7 +334,7 @@ func TestLoader(t *testing.T) {
334334
t.Errorf("did not batch queries. Expected %#v, got %#v", expected, calls)
335335
}
336336

337-
if _, found := batchOnlyLoader.cache.Get("1"); found {
337+
if _, found := batchOnlyLoader.cache.Get(ctx, "1"); found {
338338
t.Errorf("did not clear cache after batch. Expected %#v, got %#v", false, found)
339339
}
340340
})
@@ -343,8 +343,8 @@ func TestLoader(t *testing.T) {
343343
t.Parallel()
344344
identityLoader, loadCalls := IDLoader(0)
345345
ctx := context.Background()
346-
identityLoader.Prime("A", "Cached")
347-
identityLoader.Prime("B", "B")
346+
identityLoader.Prime(ctx, "A", "Cached")
347+
identityLoader.Prime(ctx, "B", "B")
348348

349349
identityLoader.ClearAll()
350350

@@ -377,12 +377,12 @@ func TestLoader(t *testing.T) {
377377
t.Parallel()
378378
identityLoader, loadCalls := NoCacheLoader(0)
379379
ctx := context.Background()
380-
identityLoader.Prime("A", "Cached")
381-
identityLoader.Prime("B", "B")
380+
identityLoader.Prime(ctx, "A", "Cached")
381+
identityLoader.Prime(ctx, "B", "B")
382382

383383
identityLoader.ClearAll()
384384

385-
future1 := identityLoader.Clear("1").Load(ctx, "1")
385+
future1 := identityLoader.Clear(ctx, "1").Load(ctx, "1")
386386
future2 := identityLoader.Load(ctx, "A")
387387
future3 := identityLoader.Load(ctx, "B")
388388

@@ -411,8 +411,8 @@ func TestLoader(t *testing.T) {
411411
t.Parallel()
412412
identityLoader, loadCalls := NoCacheLoader(0)
413413
ctx := context.Background()
414-
identityLoader.Prime("A", "Cached")
415-
identityLoader.Prime("B", "B")
414+
identityLoader.Prime(ctx, "A", "Cached")
415+
identityLoader.Prime(ctx, "B", "B")
416416

417417
future1 := identityLoader.Load(ctx, "1")
418418
future2 := identityLoader.Load(ctx, "A")

inMemoryCache.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
package dataloader
44

5-
import "sync"
5+
import (
6+
"context"
7+
"sync"
8+
)
69

710
// InMemoryCache is an in memory implementation of Cache interface.
811
// this simple implementation is well suited for
@@ -23,15 +26,15 @@ func NewCache() *InMemoryCache {
2326
}
2427

2528
// Set sets the `value` at `key` in the cache
26-
func (c *InMemoryCache) Set(key string, value Thunk) {
29+
func (c *InMemoryCache) Set(_ context.Context, key string, value Thunk) {
2730
c.mu.Lock()
2831
c.items[key] = value
2932
c.mu.Unlock()
3033
}
3134

3235
// Get gets the value at `key` if it exsits, returns value (or nil) and bool
3336
// indicating of value was found
34-
func (c *InMemoryCache) Get(key string) (Thunk, bool) {
37+
func (c *InMemoryCache) Get(_ context.Context, key string) (Thunk, bool) {
3538
c.mu.RLock()
3639
defer c.mu.RUnlock()
3740

@@ -44,7 +47,7 @@ func (c *InMemoryCache) Get(key string) (Thunk, bool) {
4447
}
4548

4649
// Delete deletes item at `key` from cache
47-
func (c *InMemoryCache) Delete(key string) bool {
50+
func (c *InMemoryCache) Delete(_ context.Context, key string) bool {
4851
if _, found := c.Get(key); found {
4952
c.mu.Lock()
5053
defer c.mu.Unlock()

0 commit comments

Comments
 (0)