Skip to content

Commit c0480dc

Browse files
refactor: Adds and applies swiftformat
1 parent 2784992 commit c0480dc

File tree

6 files changed

+214
-193
lines changed

6 files changed

+214
-193
lines changed

.swiftformat

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
--maxwidth 100
2+
--semicolons never
3+
--xcodeindentation enabled
4+
--wraparguments before-first
5+
--wrapcollections before-first
6+
--wrapconditions before-first
7+
--wrapparameters before-first

Sources/DataLoader/DataLoader.swift

+82-67
Original file line numberDiff line numberDiff line change
@@ -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. \nKeys count: \(keys.count)\nValues 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. \nKeys count: \(keys.count)\nValues 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

Sources/DataLoader/DataLoaderOptions.swift

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,33 @@ public struct DataLoaderOptions<Key: Hashable, Value> {
55
/// `batchLoadFunction` with a single load key. This is
66
/// equivalent to setting `maxBatchSize` to `1`.
77
public let batchingEnabled: Bool
8-
8+
99
/// Default `nil`. Limits the number of items that get passed in to the
1010
/// `batchLoadFn`. May be set to `1` to disable batching.
1111
public let maxBatchSize: Int?
12-
12+
1313
/// Default `true`. Set to `false` to disable memoization caching, creating a
1414
/// new `EventLoopFuture` and new key in the `batchLoadFunction`
1515
/// for every load of the same key.
1616
public let cachingEnabled: Bool
17-
17+
1818
/// Default `2ms`. Defines the period of time that the DataLoader should
1919
/// wait and collect its queue before executing. Faster times result
2020
/// in smaller batches quicker resolution, slower times result in larger
2121
/// batches but slower resolution.
2222
/// This is irrelevant if batching is disabled.
2323
public let executionPeriod: TimeAmount?
24-
24+
2525
/// Default `nil`. Produces cache key for a given load key. Useful
2626
/// when objects are keys and two objects should be considered equivalent.
2727
public let cacheKeyFunction: ((Key) -> Key)?
2828

29-
public init(batchingEnabled: Bool = true,
30-
cachingEnabled: Bool = true,
31-
maxBatchSize: Int? = nil,
32-
executionPeriod: TimeAmount? = .milliseconds(2),
33-
cacheKeyFunction: ((Key) -> Key)? = nil
29+
public init(
30+
batchingEnabled: Bool = true,
31+
cachingEnabled: Bool = true,
32+
maxBatchSize: Int? = nil,
33+
executionPeriod: TimeAmount? = .milliseconds(2),
34+
cacheKeyFunction: ((Key) -> Key)? = nil
3435
) {
3536
self.batchingEnabled = batchingEnabled
3637
self.cachingEnabled = cachingEnabled

Tests/DataLoaderTests/DataLoaderAbuseTests.swift

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import XCTest
21
import NIO
2+
import XCTest
33

44
@testable import DataLoader
55

66
/// Provides descriptive error messages for API abuse
77
class DataLoaderAbuseTests: XCTestCase {
8-
98
func testFuntionWithNoValues() throws {
109
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
1110
defer {
@@ -14,7 +13,7 @@ class DataLoaderAbuseTests: XCTestCase {
1413

1514
let identityLoader = DataLoader<Int, Int>(
1615
options: DataLoaderOptions(batchingEnabled: false)
17-
) { keys in
16+
) { _ in
1817
eventLoopGroup.next().makeSucceededFuture([])
1918
}
2019

@@ -29,13 +28,16 @@ class DataLoaderAbuseTests: XCTestCase {
2928
XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully())
3029
}
3130

32-
let identityLoader = DataLoader<Int, Int>() { keys in
31+
let identityLoader = DataLoader<Int, Int>() { _ in
3332
eventLoopGroup.next().makeSucceededFuture([])
3433
}
3534

3635
let value = try identityLoader.load(key: 1, on: eventLoopGroup)
3736

38-
XCTAssertThrowsError(try value.wait(), "The function did not return an array of the same length as the array of keys. \nKeys count: 1\nValues count: 0")
37+
XCTAssertThrowsError(
38+
try value.wait(),
39+
"The function did not return an array of the same length as the array of keys. \nKeys count: 1\nValues count: 0"
40+
)
3941
}
4042

4143
func testBatchFuntionWithSomeValues() throws {
@@ -97,4 +99,4 @@ class DataLoaderAbuseTests: XCTestCase {
9799
}
98100
}
99101

100-
extension String: Error { }
102+
extension String: Error {}

0 commit comments

Comments
 (0)