Skip to content

Commit f97328e

Browse files
committed
Add run { } throwing: { }
1 parent e6324f3 commit f97328e

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed

Sources/App/Commands/Ingest.swift

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,7 @@ extension Ingestion {
170170
let result = await Result { () async throws(Ingestion.Error) -> Joined<Package, Repository> in
171171
Current.logger().info("Ingesting \(package.package.url)")
172172
let (metadata, license, readme) = try await fetchMetadata(client: client, package: package)
173-
let repo = try await Result {
174-
try await Repository.findOrCreate(on: database, for: package.model)
175-
}.mapError {
176-
Ingestion.Error(
177-
packageId: package.model.id!,
178-
underlyingError: .findOrCreateRepositoryFailed(url: package.package.url, details: $0)
179-
)
180-
}.get()
173+
let repo = try await findOrCreateRepository(on: database, for: package)
181174

182175
let s3Readme: S3Readme?
183176
do throws(S3Readme.Error) {
@@ -190,11 +183,11 @@ extension Ingestion {
190183

191184
let fork = await getFork(on: database, parent: metadata.repository?.parent)
192185

193-
try await Result { () async throws(Ingestion.Error.UnderlyingError) in
186+
try await run { () async throws(Ingestion.Error.UnderlyingError) in
194187
try await updateRepository(on: database, for: repo, metadata: metadata, licenseInfo: license, readmeInfo: readme, s3Readme: s3Readme, fork: fork)
195-
}.mapError {
196-
Error.init(packageId: package.model.id!, underlyingError: $0)
197-
}.get()
188+
} throwing: {
189+
Ingestion.Error(packageId: package.model.id!, underlyingError: $0)
190+
}
198191
return package
199192
}
200193

@@ -213,6 +206,18 @@ extension Ingestion {
213206
}
214207

215208

209+
static func findOrCreateRepository(on database: Database, for package: Joined<Package, Repository>) async throws(Ingestion.Error) -> Repository {
210+
try await run {
211+
try await Repository.findOrCreate(on: database, for: package.model)
212+
} throwing: {
213+
Ingestion.Error(
214+
packageId: package.model.id!,
215+
underlyingError: .findOrCreateRepositoryFailed(url: package.model.url, details: $0)
216+
)
217+
}
218+
}
219+
220+
216221
static func storeS3Readme(client: Client, repository: Repository, metadata: Github.Metadata, readme: Github.Readme?) async throws(S3Readme.Error) -> S3Readme? {
217222
if let upstreamEtag = readme?.etag,
218223
repository.s3Readme?.needsUpdate(upstreamEtag: upstreamEtag) ?? true,
@@ -234,12 +239,11 @@ func fetchMetadata(client: Client, package: Joined<Package, Repository>) async t
234239
// Even though we get through a `Joined<Package, Repository>` as a parameter, it's
235240
// we must not rely on `repository` as it will be nil when a package is first ingested.
236241
// The only way to get `owner` and `repository` here is by parsing them from the URL.
237-
let (owner, repository) = try Result {
242+
let (owner, repository) = try await run {
238243
try Github.parseOwnerName(url: package.model.url)
239-
}.mapError { _ in
240-
Ingestion.Error(packageId: package.model.id!,
241-
underlyingError: .invalidURL(package.model.url))
242-
}.get()
244+
} throwing: { _ in
245+
Ingestion.Error.invalidURL(packageId: package.model.id!, url: package.model.url)
246+
}
243247

244248
async let license = await Current.fetchLicense(client, owner, repository)
245249
async let readme = await Current.fetchReadme(client, owner, repository)
@@ -352,3 +356,9 @@ private extension Github.Metadata.Parent {
352356
return normalizedURL
353357
}
354358
}
359+
360+
private extension Ingestion.Error {
361+
static func invalidURL(packageId: Package.Id, url: String) -> Self {
362+
Ingestion.Error(packageId: packageId, underlyingError: .invalidURL(url))
363+
}
364+
}

Sources/App/Core/Extensions/Result+ext.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,15 @@ extension Result where Failure == Error {
2727
}
2828

2929

30-
#warning("Add an extension `Result.mapError`")
30+
// Not really a part of the Result type but closely enough related to put here
31+
// Perhaps put this in AsyncDefer.swift and rename the file?
32+
@discardableResult
33+
func run<T, E1: Error, E2: Error>(_ operation: () async throws(E1) -> T,
34+
throwing transform: (E1) -> E2) async throws(E2) -> T {
35+
do {
36+
let result = try await operation()
37+
return result
38+
} catch {
39+
throw transform(error)
40+
}
41+
}

0 commit comments

Comments
 (0)