Skip to content

Commit 1ff30d0

Browse files
Merge pull request #3327 from SwiftPackageIndex/convert-PackageCollection-to-async-await
Convert PackageCollection related ELFs to a/a
2 parents 91a2432 + ee2ef25 commit 1ff30d0

File tree

6 files changed

+324
-358
lines changed

6 files changed

+324
-358
lines changed

Sources/App/Controllers/API/API+PackageCollectionController.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ extension API {
2323
enum PackageCollectionController {
2424

2525
@Sendable
26-
static func generate(req: Request) throws -> EventLoopFuture<SignedCollection> {
26+
static func generate(req: Request) async throws -> SignedCollection {
2727
AppMetrics.apiPackageCollectionGetTotal?.inc()
2828

2929
let dto = try req.content.decode(PostPackageCollectionDTO.self)
3030

3131
switch dto.selection {
3232
case let .author(author):
33-
return SignedCollection.generate(
33+
return try await SignedCollection.generate(
3434
db: req.db,
3535
filterBy: .author(author),
3636
authorName: dto.authorName ?? "Swift Package Index",
@@ -44,7 +44,7 @@ extension API {
4444
guard packageURLs.count <= 20 else {
4545
throw Abort(.badRequest)
4646
}
47-
return SignedCollection.generate(
47+
return try await SignedCollection.generate(
4848
db: req.db,
4949
filterBy: .urls(packageURLs),
5050
authorName: dto.authorName ?? "Swift Package Index",

Sources/App/Controllers/PackageCollectionController.swift

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,19 @@ import Vapor
1717

1818
enum PackageCollectionController {
1919
@Sendable
20-
static func generate(req: Request) throws -> EventLoopFuture<SignedCollection> {
20+
static func generate(req: Request) async throws -> SignedCollection {
2121
AppMetrics.packageCollectionGetTotal?.inc()
2222

23-
guard let owner = req.parameters.get("owner") else {
24-
return req.eventLoop.future(error: Abort(.notFound))
25-
}
23+
guard let owner = req.parameters.get("owner") else { throw Abort(.notFound) }
2624

27-
return SignedCollection.generate(
28-
db: req.db,
29-
filterBy: .author(owner),
30-
authorName: "\(owner) via the Swift Package Index"
31-
).flatMapError {
32-
if case PackageCollection.Error.noResults = $0 {
33-
return req.eventLoop.makeFailedFuture(Abort(.notFound))
34-
}
35-
return req.eventLoop.makeFailedFuture($0)
25+
do {
26+
return try await SignedCollection.generate(
27+
db: req.db,
28+
filterBy: .author(owner),
29+
authorName: "\(owner) via the Swift Package Index"
30+
)
31+
} catch PackageCollection.Error.noResults {
32+
throw Abort(.notFound)
3633
}
3734
}
3835
}

Sources/App/Core/PackageCollection+VersionResult.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension PackageCollection.VersionResult {
4040
var targets: [App.Target] { version.targets }
4141
var version: App.Version { model.version }
4242

43-
static func query(on database: Database, filterBy filter: PackageCollection.Filter) -> EventLoopFuture<[Self]> {
43+
static func query(on database: Database, filterBy filter: PackageCollection.Filter) async throws -> [Self] {
4444
let query = M
4545
.query(
4646
on: database,
@@ -59,8 +59,8 @@ extension PackageCollection.VersionResult {
5959
query.filter(App.Package.self, \.$url ~~ packageURLs)
6060
}
6161

62-
return query.all()
63-
.mapEach(Self.init(model:))
62+
return try await query.all()
63+
.map(Self.init(model:))
6464
}
6565
}
6666

Sources/App/Core/PackageCollection+generate.swift

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -44,39 +44,30 @@ extension PackageCollection {
4444
collectionName: String? = nil,
4545
keywords: [String]? = nil,
4646
overview: String? = nil,
47-
revision: Int? = nil) -> EventLoopFuture<PackageCollection> {
48-
VersionResult.query(on: db, filterBy: filter)
49-
.map { results in
50-
// Multiple versions can reference the same package, therefore
51-
// we need to group them so we don't create duplicate packages.
52-
results.groupedByPackage(sortBy: .url)
53-
}
54-
.map { groups -> ([Package], String, String) in
55-
let packages = groups.compactMap {
56-
Package.init(resultGroup: $0,
57-
keywords: keywords)
58-
}
59-
let authorLabel = authorLabel(repositories: groups.map(\.repository))
60-
let collectionName = collectionName ?? Self.collectionName(for: filter, authorLabel: authorLabel)
61-
let overview = overview ?? Self.overview(for: filter, authorLabel: authorLabel)
62-
return (packages, collectionName, overview)
63-
}
64-
.flatMap { packages, collectionName, overview in
65-
guard !packages.isEmpty else {
66-
return db.eventLoop.makeFailedFuture(Error.noResults)
67-
}
68-
return db.eventLoop.makeSucceededFuture(
69-
PackageCollection.init(
70-
name: collectionName,
71-
overview: overview,
72-
keywords: keywords,
73-
packages: packages,
74-
formatVersion: .v1_0,
75-
revision: revision,
76-
generatedAt: Current.date(),
77-
generatedBy: authorName.map(Author.init(name:)))
78-
)
79-
}
47+
revision: Int? = nil) async throws -> PackageCollection {
48+
let results = try await VersionResult.query(on: db, filterBy: filter)
49+
50+
// Multiple versions can reference the same package, therefore
51+
// we need to group them so we don't create duplicate packages.
52+
let groups = results.groupedByPackage(sortBy: .url)
53+
54+
let packages = groups.compactMap { Package.init(resultGroup: $0, keywords: keywords) }
55+
let authorLabel = authorLabel(repositories: groups.map(\.repository))
56+
let collectionName = collectionName ?? Self.collectionName(for: filter, authorLabel: authorLabel)
57+
let overview = overview ?? Self.overview(for: filter, authorLabel: authorLabel)
58+
59+
guard !packages.isEmpty else { throw Error.noResults }
60+
61+
return PackageCollection.init(
62+
name: collectionName,
63+
overview: overview,
64+
keywords: keywords,
65+
packages: packages,
66+
formatVersion: .v1_0,
67+
revision: revision,
68+
generatedAt: Current.date(),
69+
generatedBy: authorName.map(Author.init(name:))
70+
)
8071
}
8172

8273
static func authorLabel(repositories: [Repository]) -> String? {

Sources/App/Core/PackageCollection+signing.swift

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,36 +30,30 @@ extension SignedCollection {
3030
collectionName: String? = nil,
3131
keywords: [String]? = nil,
3232
overview: String? = nil,
33-
revision: Int? = nil) -> EventLoopFuture<SignedCollection> {
34-
PackageCollection.generate(db: db,
35-
filterBy: filter,
36-
authorName: authorName,
37-
collectionName: collectionName,
38-
keywords: keywords,
39-
overview: overview,
40-
revision: revision)
41-
.flatMap {
42-
sign(eventLoop: db.eventLoop, collection: $0)
43-
}
33+
revision: Int? = nil) async throws -> SignedCollection {
34+
let collection = try await PackageCollection.generate(db: db,
35+
filterBy: filter,
36+
authorName: authorName,
37+
collectionName: collectionName,
38+
keywords: keywords,
39+
overview: overview,
40+
revision: revision)
41+
return try await sign(collection: collection)
4442
}
4543

46-
static func sign(eventLoop: EventLoop, collection: PackageCollection) -> EventLoopFuture<SignedCollection> {
44+
static func sign(collection: PackageCollection) async throws -> SignedCollection {
4745
guard let privateKey = Current.collectionSigningPrivateKey() else {
48-
return eventLoop.makeFailedFuture(AppError.envVariableNotSet("COLLECTION_SIGNING_PRIVATE_KEY"))
46+
throw AppError.envVariableNotSet("COLLECTION_SIGNING_PRIVATE_KEY")
4947
}
5048

51-
return eventLoop.makeFutureWithTask {
52-
try await signer.sign(collection: collection,
53-
certChainPaths: Current.collectionSigningCertificateChain(),
54-
privateKeyPEM: privateKey)
55-
}
49+
return try await signer.sign(collection: collection,
50+
certChainPaths: Current.collectionSigningCertificateChain(),
51+
privateKeyPEM: privateKey)
5652
}
5753

58-
static func validate(eventLoop: EventLoop, signedCollection: SignedCollection) -> EventLoopFuture<Bool> {
59-
eventLoop.makeFutureWithTask {
60-
try await signer.validate(signedCollection: signedCollection)
61-
return true
62-
}
54+
static func validate(signedCollection: SignedCollection) async throws -> Bool {
55+
try await signer.validate(signedCollection: signedCollection)
56+
return true
6357
}
6458

6559
static let certsDir = URL(fileURLWithPath: Current.fileManager.workingDirectory())

0 commit comments

Comments
 (0)