@@ -6,8 +6,9 @@ public enum DataLoaderFutureValue<T> {
66 case failure( Error )
77}
88
9- public typealias BatchLoadFunction < Key, Value> = ( _ keys: [ Key ] ) throws -> EventLoopFuture < [ DataLoaderFutureValue < Value > ] >
10- private typealias LoaderQueue < Key, Value> = Array < ( key: Key , promise: EventLoopPromise < Value > ) >
9+ public typealias BatchLoadFunction < Key, Value> = ( _ keys: [ Key ] ) throws
10+ -> EventLoopFuture < [ DataLoaderFutureValue < Value > ] >
11+ private typealias LoaderQueue < Key, Value> = [ ( key: Key , promise: EventLoopPromise < Value > ) ]
1112
1213/// DataLoader creates a public API for loading data from a particular
1314/// data back-end with unique keys such as the id column of a SQL table
@@ -17,14 +18,13 @@ private typealias LoaderQueue<Key, Value> = Array<(key: Key, promise: EventLoopP
1718/// when used in long-lived applications or those which serve many users
1819/// with different access permissions and consider creating a new instance
1920/// per data request.
20- final public class DataLoader < Key: Hashable , Value> {
21-
21+ public final class DataLoader < Key: Hashable , Value> {
2222 private let batchLoadFunction : BatchLoadFunction < Key , Value >
2323 private let options : DataLoaderOptions < Key , Value >
2424
2525 private var cache = [ Key : EventLoopFuture < Value > ] ( )
2626 private var queue = LoaderQueue < Key , Value > ( )
27-
27+
2828 private var dispatchScheduled = false
2929 private let lock = Lock ( )
3030
@@ -39,7 +39,7 @@ final public class DataLoader<Key: Hashable, Value> {
3939 /// Loads a key, returning an `EventLoopFuture` for the value represented by that key.
4040 public func load( key: Key , on eventLoopGroup: EventLoopGroup ) throws -> EventLoopFuture < Value > {
4141 let cacheKey = options. cacheKeyFunction ? ( key) ?? key
42-
42+
4343 return lock. withLock {
4444 if options. cachingEnabled, let cachedFuture = cache [ cacheKey] {
4545 return cachedFuture
@@ -57,14 +57,18 @@ final public class DataLoader<Key: Hashable, Value> {
5757 }
5858 } else {
5959 do {
60- _ = try batchLoadFunction ( [ key] ) . map { results in
60+ _ = try batchLoadFunction ( [ key] ) . map { results in
6161 if results. isEmpty {
62- promise. fail ( DataLoaderError . noValueForKey ( " Did not return value for key: \( key) " ) )
62+ promise
63+ . fail (
64+ DataLoaderError
65+ . noValueForKey ( " Did not return value for key: \( key) " )
66+ )
6367 } else {
6468 let result = results [ 0 ]
6569 switch result {
66- case . success( let value) : promise. succeed ( value)
67- case . failure( let error) : promise. fail ( error)
70+ case let . success( value) : promise. succeed ( value)
71+ case let . failure( error) : promise. fail ( error)
6872 }
6973 }
7074 }
@@ -82,7 +86,7 @@ final public class DataLoader<Key: Hashable, Value> {
8286 return future
8387 }
8488 }
85-
89+
8690 /// Loads multiple keys, promising an array of values:
8791 ///
8892 /// ```
@@ -97,14 +101,17 @@ final public class DataLoader<Key: Hashable, Value> {
97101 /// myLoader.load(key: "b", on: eventLoopGroup)
98102 /// ].flatten(on: eventLoopGroup).wait()
99103 /// ```
100- public func loadMany( keys: [ Key ] , on eventLoopGroup: EventLoopGroup ) throws -> EventLoopFuture < [ Value ] > {
104+ public func loadMany(
105+ keys: [ Key ] ,
106+ on eventLoopGroup: EventLoopGroup
107+ ) throws -> EventLoopFuture < [ Value ] > {
101108 guard !keys. isEmpty else {
102109 return eventLoopGroup. next ( ) . makeSucceededFuture ( [ ] )
103110 }
104111 let futures = try keys. map { try load ( key: $0, on: eventLoopGroup) }
105112 return EventLoopFuture . whenAllSucceed ( futures, on: eventLoopGroup. next ( ) )
106113 }
107-
114+
108115 /// Clears the value at `key` from the cache, if it exists. Returns itself for
109116 /// method chaining.
110117 @discardableResult
@@ -115,7 +122,7 @@ final public class DataLoader<Key: Hashable, Value> {
115122 }
116123 return self
117124 }
118-
125+
119126 /// Clears the entire cache. To be used when some event results in unknown
120127 /// invalidations across this particular `DataLoader`. Returns itself for
121128 /// method chaining.
@@ -130,9 +137,13 @@ final public class DataLoader<Key: Hashable, Value> {
130137 /// Adds the provied key and value to the cache. If the key already exists, no
131138 /// change is made. Returns itself for method chaining.
132139 @discardableResult
133- public func prime( key: Key , value: Value , on eventLoop: EventLoopGroup ) -> DataLoader < Key , Value > {
140+ public func prime(
141+ key: Key ,
142+ value: Value ,
143+ on eventLoop: EventLoopGroup
144+ ) -> DataLoader < Key , Value > {
134145 let cacheKey = options. cacheKeyFunction ? ( key) ?? key
135-
146+
136147 lock. withLockVoid {
137148 if cache [ cacheKey] == nil {
138149 let promise : EventLoopPromise < Value > = eventLoop. next ( ) . makePromise ( )
@@ -160,27 +171,27 @@ final public class DataLoader<Key: Hashable, Value> {
160171 dispatchScheduled = false
161172 }
162173 }
163-
174+
164175 guard batch. count > 0 else {
165176 return ( )
166177 }
167178
168179 // If a maxBatchSize was provided and the queue is longer, then segment the
169180 // queue into multiple batches, otherwise treat the queue as a single batch.
170- if let maxBatchSize = options. maxBatchSize, maxBatchSize > 0 && maxBatchSize < batch. count {
171- for i in 0 ... ( batch. count / maxBatchSize) {
181+ if let maxBatchSize = options. maxBatchSize, maxBatchSize > 0 , maxBatchSize < batch. count {
182+ for i in 0 ... ( batch. count / maxBatchSize) {
172183 let startIndex = i * maxBatchSize
173184 let endIndex = ( i + 1 ) * maxBatchSize
174- let slicedBatch = batch [ startIndex..< min ( endIndex, batch. count) ]
185+ let slicedBatch = batch [ startIndex ..< min ( endIndex, batch. count) ]
175186 try executeBatch ( batch: Array ( slicedBatch) )
176187 }
177188 } else {
178- try executeBatch ( batch: batch)
189+ try executeBatch ( batch: batch)
179190 }
180191 }
181-
192+
182193 private func executeBatch( batch: LoaderQueue < Key , Value > ) throws {
183- let keys = batch. map { $0 . key }
194+ let keys = batch. map ( \ . key)
184195
185196 if keys. isEmpty {
186197 return
@@ -191,22 +202,25 @@ final public class DataLoader<Key: Hashable, Value> {
191202 do {
192203 _ = try batchLoadFunction ( keys) . flatMapThrowing { values in
193204 if values. count != keys. count {
194- throw DataLoaderError . typeError ( " The function did not return an array of the same length as the array of keys. \n Keys count: \( keys. count) \n Values count: \( values. count) " )
205+ throw DataLoaderError
206+ . typeError (
207+ " The function did not return an array of the same length as the array of keys. \n Keys count: \( keys. count) \n Values count: \( values. count) "
208+ )
195209 }
196210
197211 for entry in batch. enumerated ( ) {
198212 let result = values [ entry. offset]
199213
200214 switch result {
201- case . failure( let error) : entry. element. promise. fail ( error)
202- case . success( let value) : entry. element. promise. succeed ( value)
215+ case let . failure( error) : entry. element. promise. fail ( error)
216+ case let . success( value) : entry. element. promise. succeed ( value)
203217 }
204218 }
205219 } . recover { error in
206220 self . failedExecution ( batch: batch, error: error)
207221 }
208222 } catch {
209- self . failedExecution ( batch: batch, error: error)
223+ failedExecution ( batch: batch, error: error)
210224 }
211225 }
212226
@@ -220,48 +234,49 @@ final public class DataLoader<Key: Hashable, Value> {
220234
221235#if compiler(>=5.5) && canImport(_Concurrency)
222236
223- /// Batch load function using async await
224- public typealias ConcurrentBatchLoadFunction < Key, Value> = @Sendable ( _ keys: [ Key ] ) async throws -> [ DataLoaderFutureValue < Value > ]
237+ /// Batch load function using async await
238+ public typealias ConcurrentBatchLoadFunction < Key, Value> =
239+ @Sendable ( _ keys: [ Key ] ) async throws -> [ DataLoaderFutureValue < Value > ]
225240
226- public extension DataLoader {
227- @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
228- convenience init (
229- on eventLoop: EventLoop ,
230- options: DataLoaderOptions < Key , Value > = DataLoaderOptions ( ) ,
231- throwing asyncThrowingLoadFunction: @escaping ConcurrentBatchLoadFunction < Key , Value >
232- ) {
233- self . init ( options: options, batchLoadFunction: { keys in
234- let promise = eventLoop. next ( ) . makePromise ( of: [ DataLoaderFutureValue < Value > ] . self)
235- promise. completeWithTask {
236- try await asyncThrowingLoadFunction ( keys)
237- }
238- return promise. futureResult
239- } )
240- }
241+ public extension DataLoader {
242+ @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
243+ convenience init (
244+ on eventLoop: EventLoop ,
245+ options: DataLoaderOptions < Key , Value > = DataLoaderOptions ( ) ,
246+ throwing asyncThrowingLoadFunction: @escaping ConcurrentBatchLoadFunction < Key , Value >
247+ ) {
248+ self . init ( options: options, batchLoadFunction: { keys in
249+ let promise = eventLoop. next ( ) . makePromise ( of: [ DataLoaderFutureValue < Value > ] . self)
250+ promise. completeWithTask {
251+ try await asyncThrowingLoadFunction ( keys)
252+ }
253+ return promise. futureResult
254+ } )
255+ }
241256
242- /// Asynchronously loads a key, returning the value represented by that key.
243- @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
244- func load( key: Key , on eventLoopGroup: EventLoopGroup ) async throws -> Value {
245- try await load ( key: key, on: eventLoopGroup) . get ( )
246- }
257+ /// Asynchronously loads a key, returning the value represented by that key.
258+ @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
259+ func load( key: Key , on eventLoopGroup: EventLoopGroup ) async throws -> Value {
260+ try await load ( key: key, on: eventLoopGroup) . get ( )
261+ }
247262
248- /// Asynchronously loads multiple keys, promising an array of values:
249- ///
250- /// ```
251- /// let aAndB = try await myLoader.loadMany(keys: [ "a", "b" ], on: eventLoopGroup)
252- /// ```
253- ///
254- /// This is equivalent to the more verbose:
255- ///
256- /// ```
257- /// async let a = myLoader.load(key: "a", on: eventLoopGroup)
258- /// async let b = myLoader.load(key: "b", on: eventLoopGroup)
259- /// let aAndB = try await a + b
260- /// ```
261- @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
262- func loadMany( keys: [ Key ] , on eventLoopGroup: EventLoopGroup ) async throws -> [ Value ] {
263- try await loadMany ( keys: keys, on: eventLoopGroup) . get ( )
263+ /// Asynchronously loads multiple keys, promising an array of values:
264+ ///
265+ /// ```
266+ /// let aAndB = try await myLoader.loadMany(keys: [ "a", "b" ], on: eventLoopGroup)
267+ /// ```
268+ ///
269+ /// This is equivalent to the more verbose:
270+ ///
271+ /// ```
272+ /// async let a = myLoader.load(key: "a", on: eventLoopGroup)
273+ /// async let b = myLoader.load(key: "b", on: eventLoopGroup)
274+ /// let aAndB = try await a + b
275+ /// ```
276+ @available ( macOS 12 , iOS 15 , watchOS 8 , tvOS 15 , * )
277+ func loadMany( keys: [ Key ] , on eventLoopGroup: EventLoopGroup ) async throws -> [ Value ] {
278+ try await loadMany ( keys: keys, on: eventLoopGroup) . get ( )
279+ }
264280 }
265- }
266281
267- #endif
282+ #endif
0 commit comments