@@ -14,29 +14,6 @@ import (
14
14
// Loader is the function type for loading data
15
15
type Loader [K comparable , V any ] func (context.Context , []K ) []Result [V ]
16
16
17
- // config holds the configuration for DataLoader
18
- type config struct {
19
- // BatchSize is the number of keys to batch together, Default is 100
20
- BatchSize int
21
- // Wait is the duration to wait before processing a batch, Default is 16ms
22
- Wait time.Duration
23
- // CacheSize is the size of the cache, Default is 1024
24
- CacheSize int
25
- // CacheExpire is the duration to expire cache items, Default is 1 minute
26
- CacheExpire time.Duration
27
- }
28
-
29
- // dataLoader is the main struct for the dataloader
30
- type dataLoader [K comparable , V any ] struct {
31
- loader Loader [K , V ]
32
- cache * expirable.LRU [K , V ]
33
- config config
34
- mu sync.Mutex
35
- batch []K
36
- chs map [K ][]chan Result [V ]
37
- stopSchedule chan struct {}
38
- }
39
-
40
17
// Interface is a `DataLoader` Interface which defines a public API for loading data from a particular
41
18
// data back-end with unique keys such as the `id` column of a SQL table or
42
19
// document name in a MongoDB database, given a batch loading function.
@@ -60,6 +37,29 @@ type Interface[K comparable, V any] interface {
60
37
Prime (ctx context.Context , key K , value V ) Interface [K , V ]
61
38
}
62
39
40
+ // config holds the configuration for DataLoader
41
+ type config struct {
42
+ // BatchSize is the number of keys to batch together, Default is 100
43
+ BatchSize int
44
+ // Wait is the duration to wait before processing a batch, Default is 16ms
45
+ Wait time.Duration
46
+ // CacheSize is the size of the cache, Default is 1024
47
+ CacheSize int
48
+ // CacheExpire is the duration to expire cache items, Default is 1 minute
49
+ CacheExpire time.Duration
50
+ }
51
+
52
+ // dataLoader is the main struct for the dataloader
53
+ type dataLoader [K comparable , V any ] struct {
54
+ loader Loader [K , V ]
55
+ cache * expirable.LRU [K , V ]
56
+ config config
57
+ mu sync.Mutex
58
+ batch []K
59
+ chs map [K ][]chan Result [V ]
60
+ stopSchedule chan struct {}
61
+ }
62
+
63
63
// New creates a new DataLoader with the given loader function and options
64
64
func New [K comparable , V any ](loader Loader [K , V ], options ... Option ) Interface [K , V ] {
65
65
config := config {
@@ -88,29 +88,68 @@ func New[K comparable, V any](loader Loader[K, V], options ...Option) Interface[
88
88
return dl
89
89
}
90
90
91
- // Option is a function type for configuring DataLoader
92
- type Option func (* config )
91
+ // Load loads a single key
92
+ func (d * dataLoader [K , V ]) Load (ctx context.Context , key K ) Result [V ] {
93
+ return <- d .goLoad (ctx , key )
94
+ }
95
+
96
+ // LoadMany loads multiple keys
97
+ func (d * dataLoader [K , V ]) LoadMany (ctx context.Context , keys []K ) []Result [V ] {
98
+ chs := make ([]<- chan Result [V ], len (keys ))
99
+ for i , key := range keys {
100
+ chs [i ] = d .goLoad (ctx , key )
101
+ }
102
+
103
+ results := make ([]Result [V ], len (keys ))
104
+ for i , ch := range chs {
105
+ results [i ] = <- ch
106
+ }
107
+
108
+ return results
109
+ }
110
+
111
+ // LoadMap loads multiple keys and returns a map of results
112
+ func (d * dataLoader [K , V ]) LoadMap (ctx context.Context , keys []K ) map [K ]Result [V ] {
113
+ chs := make ([]<- chan Result [V ], len (keys ))
114
+ for i , key := range keys {
115
+ chs [i ] = d .goLoad (ctx , key )
116
+ }
117
+
118
+ results := make (map [K ]Result [V ], len (keys ))
119
+ for i , ch := range chs {
120
+ results [keys [i ]] = <- ch
121
+ }
93
122
94
- // WithCache sets the cache size for the DataLoader
95
- func WithCache (size int , expire time.Duration ) Option {
96
- return func (c * config ) {
97
- c .CacheSize = size
98
- c .CacheExpire = expire
123
+ return results
124
+ }
125
+
126
+ // Clear removes an item from the cache
127
+ func (d * dataLoader [K , V ]) Clear (key K ) Interface [K , V ] {
128
+ if d .cache != nil {
129
+ d .cache .Remove (key )
99
130
}
131
+
132
+ return d
100
133
}
101
134
102
- // WithBatchSize sets the batch size for the DataLoader
103
- func WithBatchSize ( size int ) Option {
104
- return func ( c * config ) {
105
- c . BatchSize = size
135
+ // ClearAll clears the entire cache
136
+ func ( d * dataLoader [ K , V ]) ClearAll () Interface [ K , V ] {
137
+ if d . cache != nil {
138
+ d . cache . Purge ()
106
139
}
140
+
141
+ return d
107
142
}
108
143
109
- // WithWait sets the wait duration for the DataLoader
110
- func WithWait (wait time.Duration ) Option {
111
- return func (c * config ) {
112
- c .Wait = wait
144
+ // Prime primes the cache with a key and value
145
+ func (d * dataLoader [K , V ]) Prime (ctx context.Context , key K , value V ) Interface [K , V ] {
146
+ if d .cache != nil {
147
+ if _ , ok := d .cache .Get (key ); ok {
148
+ d .cache .Add (key , value )
149
+ }
113
150
}
151
+
152
+ return d
114
153
}
115
154
116
155
// goLoad loads a single key asynchronously
@@ -160,47 +199,6 @@ func (d *dataLoader[K, V]) goLoad(ctx context.Context, key K) <-chan Result[V] {
160
199
return ch
161
200
}
162
201
163
- // Load loads a single key
164
- func (d * dataLoader [K , V ]) Load (ctx context.Context , key K ) Result [V ] {
165
- return <- d .goLoad (ctx , key )
166
- }
167
-
168
- // LoadMany loads multiple keys
169
- func (d * dataLoader [K , V ]) LoadMany (ctx context.Context , keys []K ) []Result [V ] {
170
- chs := make ([]<- chan Result [V ], len (keys ))
171
- for i , key := range keys {
172
- chs [i ] = d .goLoad (ctx , key )
173
- }
174
-
175
- results := make ([]Result [V ], len (keys ))
176
- for i , ch := range chs {
177
- results [i ] = <- ch
178
- }
179
-
180
- return results
181
- }
182
-
183
- // LoadMap loads multiple keys and returns a map of results
184
- func (d * dataLoader [K , V ]) LoadMap (ctx context.Context , keys []K ) map [K ]Result [V ] {
185
- chs := make ([]<- chan Result [V ], len (keys ))
186
- for i , key := range keys {
187
- chs [i ] = d .goLoad (ctx , key )
188
- }
189
-
190
- results := make (map [K ]Result [V ], len (keys ))
191
- for i , ch := range chs {
192
- results [keys [i ]] = <- ch
193
- }
194
-
195
- return results
196
- }
197
-
198
- // reset resets the DataLoader
199
- func (d * dataLoader [K , V ]) reset () {
200
- d .batch = make ([]K , 0 , d .config .BatchSize )
201
- d .chs = make (map [K ][]chan Result [V ], d .config .BatchSize )
202
- }
203
-
204
202
// scheduleBatch schedules a batch to be processed
205
203
func (d * dataLoader [K , V ]) scheduleBatch (ctx context.Context , stopSchedule <- chan struct {}) {
206
204
select {
@@ -223,11 +221,12 @@ func (d *dataLoader[K, V]) processBatch(ctx context.Context, keys []K, chs map[K
223
221
const size = 64 << 10
224
222
buf := make ([]byte , size )
225
223
buf = buf [:runtime .Stack (buf , false )]
226
- fmt .Fprintf (os .Stderr , "Dataloader: Panic received in loader function: %v\n %s" , r , buf )
224
+ err := fmt .Errorf ("dataloader: panic received in loader function: %v" , r )
225
+ fmt .Fprintf (os .Stderr , "%v\n %s" , err , buf )
227
226
228
227
for _ , chs := range chs {
229
228
for _ , ch := range chs {
230
- ch <- Result [V ]{err : fmt . Errorf ( "panic received in loader function: %v" , r ) }
229
+ ch <- Result [V ]{err : err }
231
230
close (ch )
232
231
}
233
232
}
@@ -245,39 +244,16 @@ func (d *dataLoader[K, V]) processBatch(ctx context.Context, keys []K, chs map[K
245
244
}
246
245
}
247
246
247
+ // reset resets the DataLoader
248
+ func (d * dataLoader [K , V ]) reset () {
249
+ d .batch = make ([]K , 0 , d .config .BatchSize )
250
+ d .chs = make (map [K ][]chan Result [V ], d .config .BatchSize )
251
+ }
252
+
248
253
// sendResult sends a result to channels
249
254
func sendResult [V any ](chs []chan Result [V ], result Result [V ]) {
250
255
for _ , ch := range chs {
251
256
ch <- result
252
257
close (ch )
253
258
}
254
259
}
255
-
256
- // Clear removes an item from the cache
257
- func (d * dataLoader [K , V ]) Clear (key K ) Interface [K , V ] {
258
- if d .cache != nil {
259
- d .cache .Remove (key )
260
- }
261
-
262
- return d
263
- }
264
-
265
- // ClearAll clears the entire cache
266
- func (d * dataLoader [K , V ]) ClearAll () Interface [K , V ] {
267
- if d .cache != nil {
268
- d .cache .Purge ()
269
- }
270
-
271
- return d
272
- }
273
-
274
- // Prime primes the cache with a key and value
275
- func (d * dataLoader [K , V ]) Prime (ctx context.Context , key K , value V ) Interface [K , V ] {
276
- if d .cache != nil {
277
- if _ , ok := d .cache .Get (key ); ok {
278
- d .cache .Add (key , value )
279
- }
280
- }
281
-
282
- return d
283
- }
0 commit comments