From 9cd440282bc4c3cde7ebe603745768ba11566f6a Mon Sep 17 00:00:00 2001 From: Jay Herron Date: Sun, 5 Apr 2026 01:45:22 -0600 Subject: [PATCH 1/2] chore: Add swift-format file --- .swift-format | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .swift-format diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..1ffdbf5 --- /dev/null +++ b/.swift-format @@ -0,0 +1,7 @@ +{ + "version": 1, + "indentation" : { + "spaces" : 4 + }, + "lineBreakBeforeEachArgument": true +} From 852b6570c2b04829ae17d9673d0b2d4a019ae689 Mon Sep 17 00:00:00 2001 From: Jay Herron Date: Sun, 5 Apr 2026 01:50:05 -0600 Subject: [PATCH 2/2] refactor: Applies formatter --- Sources/AsyncDataLoader/Channel.swift | 4 +- Sources/AsyncDataLoader/DataLoader.swift | 23 ++++---- Sources/DataLoader/DataLoader.swift | 53 ++++++++++--------- .../DataLoaderAbuseTests.swift | 7 +-- .../DataLoaderTests.swift | 9 ++-- .../DataLoaderAbuseTests.swift | 7 +-- .../DataLoaderAsyncTests.swift | 3 +- Tests/DataLoaderTests/DataLoaderTests.swift | 5 +- 8 files changed, 59 insertions(+), 52 deletions(-) diff --git a/Sources/AsyncDataLoader/Channel.swift b/Sources/AsyncDataLoader/Channel.swift index 163220f..861d5e2 100644 --- a/Sources/AsyncDataLoader/Channel.swift +++ b/Sources/AsyncDataLoader/Channel.swift @@ -41,9 +41,9 @@ extension Channel { try await withCheckedThrowingContinuation { continuation in Task { switch result { - case let .success(success): + case .success(let success): continuation.resume(returning: success) - case let .failure(failure): + case .failure(let failure): continuation.resume(throwing: failure) case nil: waiters.append(continuation) diff --git a/Sources/AsyncDataLoader/DataLoader.swift b/Sources/AsyncDataLoader/DataLoader.swift index d60b829..cd84750 100644 --- a/Sources/AsyncDataLoader/DataLoader.swift +++ b/Sources/AsyncDataLoader/DataLoader.swift @@ -65,18 +65,16 @@ public actor DataLoader { let results = try await self.batchLoadFunction([key]) if results.isEmpty { - await channel - .fail( - DataLoaderError - .noValueForKey("Did not return value for key: \(key)") - ) + await channel.fail( + DataLoaderError.noValueForKey("Did not return value for key: \(key)") + ) } else { let result = results[0] switch result { - case let .success(value): + case .success(let value): await channel.fulfill(value) - case let .failure(error): + case .failure(let error): await channel.fail(error) } } @@ -198,19 +196,18 @@ public actor DataLoader { let values = try await batchLoadFunction(keys) if values.count != keys.count { - 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)" - ) + 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)" + ) } for entry in batch.enumerated() { let result = values[entry.offset] switch result { - case let .failure(error): + case .failure(let error): await entry.element.channel.fail(error) - case let .success(value): + case .success(let value): await entry.element.channel.fulfill(value) } } diff --git a/Sources/DataLoader/DataLoader.swift b/Sources/DataLoader/DataLoader.swift index 65d9e78..cf90525 100644 --- a/Sources/DataLoader/DataLoader.swift +++ b/Sources/DataLoader/DataLoader.swift @@ -59,16 +59,16 @@ public final class DataLoader { do { _ = try batchLoadFunction([key]).map { results in if results.isEmpty { - promise - .fail( - DataLoaderError - .noValueForKey("Did not return value for key: \(key)") + promise.fail( + DataLoaderError.noValueForKey( + "Did not return value for key: \(key)" ) + ) } else { let result = results[0] switch result { - case let .success(value): promise.succeed(value) - case let .failure(error): promise.fail(error) + case .success(let value): promise.succeed(value) + case .failure(let error): promise.fail(error) } } } @@ -179,10 +179,10 @@ public final class DataLoader { // If a maxBatchSize was provided and the queue is longer, then segment the // queue into multiple batches, otherwise treat the queue as a single batch. if let maxBatchSize = options.maxBatchSize, maxBatchSize > 0, maxBatchSize < batch.count { - for i in 0 ... (batch.count / maxBatchSize) { + for i in 0...(batch.count / maxBatchSize) { let startIndex = i * maxBatchSize let endIndex = (i + 1) * maxBatchSize - let slicedBatch = batch[startIndex ..< min(endIndex, batch.count)] + let slicedBatch = batch[startIndex.. { do { _ = try batchLoadFunction(keys).flatMapThrowing { values in if values.count != keys.count { - 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)" - ) + 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)" + ) } for entry in batch.enumerated() { let result = values[entry.offset] switch result { - case let .failure(error): entry.element.promise.fail(error) - case let .success(value): entry.element.promise.succeed(value) + case .failure(let error): entry.element.promise.fail(error) + case .success(let value): entry.element.promise.succeed(value) } } }.recover { error in @@ -238,25 +237,30 @@ public final class DataLoader { public typealias ConcurrentBatchLoadFunction = @Sendable (_ keys: [Key]) async throws -> [DataLoaderFutureValue] - public extension DataLoader { + extension DataLoader { @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) - convenience init( + public convenience init( on eventLoop: EventLoop, options: DataLoaderOptions = DataLoaderOptions(), throwing asyncThrowingLoadFunction: @escaping ConcurrentBatchLoadFunction ) { - self.init(options: options, batchLoadFunction: { keys in - let promise = eventLoop.next().makePromise(of: [DataLoaderFutureValue].self) - promise.completeWithTask { - try await asyncThrowingLoadFunction(keys) + self.init( + options: options, + batchLoadFunction: { keys in + let promise = eventLoop.next().makePromise( + of: [DataLoaderFutureValue].self + ) + promise.completeWithTask { + try await asyncThrowingLoadFunction(keys) + } + return promise.futureResult } - return promise.futureResult - }) + ) } /// Asynchronously loads a key, returning the value represented by that key. @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) - func load(key: Key, on eventLoopGroup: EventLoopGroup) async throws -> Value { + public func load(key: Key, on eventLoopGroup: EventLoopGroup) async throws -> Value { try await load(key: key, on: eventLoopGroup).get() } @@ -274,7 +278,8 @@ public final class DataLoader { /// let aAndB = try await a + b /// ``` @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) - func loadMany(keys: [Key], on eventLoopGroup: EventLoopGroup) async throws -> [Value] { + public func loadMany(keys: [Key], on eventLoopGroup: EventLoopGroup) async throws -> [Value] + { try await loadMany(keys: keys, on: eventLoopGroup).get() } } diff --git a/Tests/AsyncDataLoaderTests/DataLoaderAbuseTests.swift b/Tests/AsyncDataLoaderTests/DataLoaderAbuseTests.swift index 4224a44..57a50b2 100644 --- a/Tests/AsyncDataLoaderTests/DataLoaderAbuseTests.swift +++ b/Tests/AsyncDataLoaderTests/DataLoaderAbuseTests.swift @@ -1,6 +1,7 @@ -@testable import AsyncDataLoader import XCTest +@testable import AsyncDataLoader + /// Provides descriptive error messages for API abuse class DataLoaderAbuseTests: XCTestCase { func testFuntionWithNoValues() async throws { @@ -24,7 +25,7 @@ class DataLoaderAbuseTests: XCTestCase { } func testBatchFuntionMustPromiseAnArrayOfCorrectLength() async { - let identityLoader = DataLoader() { _ in + let identityLoader = DataLoader { _ in [] } @@ -42,7 +43,7 @@ class DataLoaderAbuseTests: XCTestCase { } func testBatchFuntionWithSomeValues() async throws { - let identityLoader = DataLoader() { keys in + let identityLoader = DataLoader { keys in var results = [DataLoaderValue]() for key in keys { diff --git a/Tests/AsyncDataLoaderTests/DataLoaderTests.swift b/Tests/AsyncDataLoaderTests/DataLoaderTests.swift index daa52a5..64e13d1 100644 --- a/Tests/AsyncDataLoaderTests/DataLoaderTests.swift +++ b/Tests/AsyncDataLoaderTests/DataLoaderTests.swift @@ -1,6 +1,7 @@ -@testable import AsyncDataLoader import XCTest +@testable import AsyncDataLoader + let sleepConstant = UInt64(2_000_000) actor Concurrent { @@ -39,7 +40,7 @@ final class DataLoaderTests: XCTestCase { /// Supports loading multiple keys in one call func testLoadingMultipleKeys() async throws { - let identityLoader = DataLoader() { keys in + let identityLoader = DataLoader { keys in keys.map { DataLoaderValue.success($0) } } @@ -618,7 +619,7 @@ final class DataLoaderTests: XCTestCase { var didFailWithErrorText2 = "" switch didFailWithError2 { - case let .typeError(text): + case .typeError(let text): didFailWithErrorText2 = text case .noValueForKey: break @@ -648,7 +649,7 @@ final class DataLoaderTests: XCTestCase { var didFailWithErrorText3 = "" switch didFailWithError3 { - case let .typeError(text): + case .typeError(let text): didFailWithErrorText3 = text case .noValueForKey: break diff --git a/Tests/DataLoaderTests/DataLoaderAbuseTests.swift b/Tests/DataLoaderTests/DataLoaderAbuseTests.swift index 561aa11..8f679a1 100644 --- a/Tests/DataLoaderTests/DataLoaderAbuseTests.swift +++ b/Tests/DataLoaderTests/DataLoaderAbuseTests.swift @@ -1,7 +1,8 @@ -@testable import DataLoader import NIOPosix import XCTest +@testable import DataLoader + /// Provides descriptive error messages for API abuse class DataLoaderAbuseTests: XCTestCase { func testFuntionWithNoValues() throws { @@ -30,7 +31,7 @@ class DataLoaderAbuseTests: XCTestCase { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let identityLoader = DataLoader() { _ in + let identityLoader = DataLoader { _ in eventLoopGroup.next().makeSucceededFuture([]) } @@ -48,7 +49,7 @@ class DataLoaderAbuseTests: XCTestCase { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let identityLoader = DataLoader() { keys in + let identityLoader = DataLoader { keys in var results = [DataLoaderFutureValue]() for key in keys { diff --git a/Tests/DataLoaderTests/DataLoaderAsyncTests.swift b/Tests/DataLoaderTests/DataLoaderAsyncTests.swift index 19633a4..a3c66e4 100644 --- a/Tests/DataLoaderTests/DataLoaderAsyncTests.swift +++ b/Tests/DataLoaderTests/DataLoaderAsyncTests.swift @@ -1,7 +1,8 @@ -@testable import DataLoader import NIOPosix import XCTest +@testable import DataLoader + #if compiler(>=5.5) && canImport(_Concurrency) @available(macOS 12, iOS 15, watchOS 8, tvOS 15, *) diff --git a/Tests/DataLoaderTests/DataLoaderTests.swift b/Tests/DataLoaderTests/DataLoaderTests.swift index 8b7d648..8c8765f 100644 --- a/Tests/DataLoaderTests/DataLoaderTests.swift +++ b/Tests/DataLoaderTests/DataLoaderTests.swift @@ -1,8 +1,9 @@ -@testable import DataLoader import NIOCore import NIOPosix import XCTest +@testable import DataLoader + /// Primary API final class DataLoaderTests: XCTestCase { /// Builds a really really simple data loader' @@ -32,7 +33,7 @@ final class DataLoaderTests: XCTestCase { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let identityLoader = DataLoader() { keys in + let identityLoader = DataLoader { keys in let results = keys.map { DataLoaderFutureValue.success($0) } return eventLoopGroup.next().makeSucceededFuture(results)