1
1
# DataLoader
2
+
3
+ [ ![ ] ( https://img.shields.io/badge/License-MIT-blue.svg?style=flat )] ( https://tldrlegal.com/license/mit-license )
4
+ [ ![ ] ( https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FGraphQLSwift%2FDataLoader%2Fbadge%3Ftype%3Dswift-versions )] ( https://swiftpackageindex.com/GraphQLSwift/DataLoader )
5
+ [ ![ ] ( https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FGraphQLSwift%2FDataLoader%2Fbadge%3Ftype%3Dplatforms )] ( https://swiftpackageindex.com/GraphQLSwift/DataLoader )
6
+
2
7
DataLoader is a generic utility to be used as part of your application's data fetching layer to provide a simplified and consistent API over various remote data sources such as databases or web services via batching and caching.
3
8
4
9
This is a Swift version of the Facebook [ DataLoader] ( https://github.com/facebook/dataloader ) .
5
10
6
- [ ![ Swift] [ swift-badge ]] [ swift-url ]
7
- [ ![ License] [ mit-badge ]] [ mit-url ]
8
-
9
11
## Gettings started 🚀
10
12
11
13
Include this repo in your ` Package.swift ` file.
@@ -40,7 +42,7 @@ let future2 = try userLoader.load(key: 2, on: eventLoopGroup)
40
42
let future3 = try userLoader.load (key : 1 , on : eventLoopGroup)
41
43
```
42
44
43
- The example above will only fetch two users, because the user with key ` 1 ` is present twice in the list.
45
+ The example above will only fetch two users, because the user with key ` 1 ` is present twice in the list.
44
46
45
47
### Load multiple keys
46
48
There is also a method to load multiple keys at once
@@ -50,14 +52,14 @@ try userLoader.loadMany(keys: [1, 2, 3], on: eventLoopGroup)
50
52
51
53
### Execution
52
54
By default, a DataLoader will wait for a short time from the moment ` load ` is called to collect keys prior
53
- to running the ` batchLoadFunction ` and completing the ` load ` futures. This is to let keys accumulate and
54
- batch into a smaller number of total requests. This amount of time is configurable using the ` executionPeriod `
55
+ to running the ` batchLoadFunction ` and completing the ` load ` futures. This is to let keys accumulate and
56
+ batch into a smaller number of total requests. This amount of time is configurable using the ` executionPeriod `
55
57
option:
56
58
57
59
``` swift
58
60
let myLoader = DataLoader< String , String > (
59
61
options : DataLoaderOptions (executionPeriod : .milliseconds (50 )),
60
- batchLoadFunction : { keys in
62
+ batchLoadFunction : { keys in
61
63
self .someBatchLoader (keys : keys).map { DataLoaderFutureValue.success ($0 ) }
62
64
}
63
65
)
@@ -66,10 +68,10 @@ let myLoader = DataLoader<String, String>(
66
68
Longer execution periods reduce the number of total data requests, but also reduce the responsiveness of the
67
69
` load ` futures.
68
70
69
- If desired, you can manually execute the ` batchLoadFunction ` and complete the futures at any time, using the
71
+ If desired, you can manually execute the ` batchLoadFunction ` and complete the futures at any time, using the
70
72
` .execute() ` method.
71
73
72
- Scheduled execution can be disabled by setting ` executionPeriod ` to ` nil ` , but be careful - you * must* call ` .execute() `
74
+ Scheduled execution can be disabled by setting ` executionPeriod ` to ` nil ` , but be careful - you * must* call ` .execute() `
73
75
manually in this case. Otherwise, the futures will never complete!
74
76
75
77
### Disable batching
@@ -78,10 +80,10 @@ In this case, the `batchLoadFunction` will be invoked immediately when a key is
78
80
79
81
80
82
## Caching 💰
81
- DataLoader provides a memoization cache. After ` .load() ` is called with a key, the resulting value is cached
83
+ DataLoader provides a memoization cache. After ` .load() ` is called with a key, the resulting value is cached
82
84
for the lifetime of the DataLoader object. This eliminates redundant loads.
83
85
84
- In addition to relieving pressure on your data storage, caching results also creates fewer objects which may
86
+ In addition to relieving pressure on your data storage, caching results also creates fewer objects which may
85
87
relieve memory pressure on your application:
86
88
87
89
``` swift
@@ -132,15 +134,15 @@ userLoader.load(key: 4, on: eventLoopGroup)
132
134
133
135
### Caching Errors
134
136
135
- If a batch load fails (that is, a batch function throws or returns a DataLoaderFutureValue.failure(Error)),
137
+ If a batch load fails (that is, a batch function throws or returns a DataLoaderFutureValue.failure(Error)),
136
138
then the requested values will not be cached. However if a batch
137
139
function returns an ` Error ` instance for an individual value, that ` Error ` will
138
140
be cached to avoid frequently loading the same ` Error ` .
139
141
140
142
In some circumstances you may wish to clear the cache for these individual Errors:
141
143
142
144
``` swift
143
- userLoader.load (key : 1 , on : eventLoopGroup).whenFailure { error in
145
+ userLoader.load (key : 1 , on : eventLoopGroup).whenFailure { error in
144
146
if (/* determine if should clear error */ ) {
145
147
userLoader.clear (key : 1 );
146
148
}
@@ -165,7 +167,7 @@ For example:
165
167
``` swift
166
168
let myLoader = DataLoader< String , String > (
167
169
options : DataLoaderOptions (cachingEnabled : false ),
168
- batchLoadFunction : { keys in
170
+ batchLoadFunction : { keys in
169
171
self .someBatchLoader (keys : keys).map { DataLoaderFutureValue.success ($0 ) }
170
172
}
171
173
)
@@ -193,7 +195,7 @@ let myLoader = DataLoader<String, String>(batchLoadFunction: { keys in
193
195
## Using with GraphQL 🎀
194
196
195
197
DataLoader pairs nicely well with [ GraphQL] ( https://github.com/GraphQLSwift/GraphQL ) and
196
- [ Graphiti] ( https://github.com/GraphQLSwift/Graphiti ) . GraphQL fields are designed to be
198
+ [ Graphiti] ( https://github.com/GraphQLSwift/Graphiti ) . GraphQL fields are designed to be
197
199
stand-alone functions. Without a caching or batching mechanism,
198
200
it's easy for a naive GraphQL server to issue new database requests each time a
199
201
field is resolved.
@@ -220,7 +222,7 @@ Consider the following GraphQL request:
220
222
Naively, if ` me ` , ` bestFriend ` and ` friends ` each need to request the backend,
221
223
there could be at most 12 database requests!
222
224
223
- By using DataLoader, we could batch our requests to a ` User ` type, and
225
+ By using DataLoader, we could batch our requests to a ` User ` type, and
224
226
only require at most 4 database requests, and possibly fewer if there are cache hits.
225
227
Here's a full example using Graphiti:
226
228
@@ -230,11 +232,11 @@ struct User : Codable {
230
232
let name: String
231
233
let bestFriendID: Int
232
234
let friendIDs: [Int ]
233
-
235
+
234
236
func getBestFriend (context : UserContext, arguments : NoArguments, group : EventLoopGroup) throws -> EventLoopFuture<User> {
235
237
return try context.userLoader .load (key : user.bestFriendID , on : group)
236
238
}
237
-
239
+
238
240
struct FriendArguments {
239
241
first: Int
240
242
}
@@ -271,7 +273,7 @@ struct UserAPI : API {
271
273
Argument (" first" , at : .\first)
272
274
}
273
275
}
274
-
276
+
275
277
Query {
276
278
Field (" me" , at : UserResolver.hero , as : User.self )
277
279
}
@@ -299,14 +301,6 @@ swiftformat .
299
301
300
302
## Acknowledgements 👏
301
303
302
- This library is entirely a Swift version of Facebooks [ DataLoader] ( https://github.com/facebook/dataloader ) .
303
- Developed by [ Lee Byron] ( https://github.com/leebyron ) and [ Nicholas Schrock] ( https://github.com/schrockn )
304
+ This library is entirely a Swift version of Facebooks [ DataLoader] ( https://github.com/facebook/dataloader ) .
305
+ Developed by [ Lee Byron] ( https://github.com/leebyron ) and [ Nicholas Schrock] ( https://github.com/schrockn )
304
306
from [ Facebook] ( https://www.facebook.com/ ) .
305
-
306
-
307
-
308
- [ swift-badge ] : https://img.shields.io/badge/Swift-5.2-orange.svg?style=flat
309
- [ swift-url ] : https://swift.org
310
-
311
- [ mit-badge ] : https://img.shields.io/badge/License-MIT-blue.svg?style=flat
312
- [ mit-url ] : https://tldrlegal.com/license/mit-license
0 commit comments