@@ -271,30 +271,66 @@ enum Ingestion {
271271 throw Github . Error. requestFailed ( . internalServerError)
272272 }
273273
274- // Need to pull in github functions individually, because otherwise the `async let` will trigger a
275- // concurrency error if github gets used more than once:
276- // Sending 'github' into async let risks causing data races between async let uses and local uses
277- @Dependency ( \. github. fetchMetadata) var fetchMetadata
278- @Dependency ( \. github. fetchLicense) var fetchLicense
279- @Dependency ( \. github. fetchReadme) var fetchReadme
274+ // 2026-04-08, sas: revert this back to `async let` instead of `withThrowingTaskGroup` when a fix for https://github.com/swiftlang/swift/issues/75501 is available.
275+ do {
276+ enum FetchResult : Sendable {
277+ case metadata( Github . Metadata )
278+ case license( Github . License ? )
279+ case readme( Github . Readme ? )
280+ }
280281
281- async let metadata = try await fetchMetadata ( owner, repository)
282- async let license = await fetchLicense ( owner, repository)
283- async let readme = await fetchReadme ( owner, repository)
282+ let results = try await withThrowingTaskGroup ( of: FetchResult . self) { group in
283+ group. addTask {
284+ @Dependency ( \. github. fetchMetadata) var fetchMetadata
285+ return . metadata( try await fetchMetadata ( owner, repository) )
286+ }
287+ group. addTask {
288+ @Dependency ( \. github. fetchLicense) var fetchLicense
289+ return . license( await fetchLicense ( owner, repository) )
290+ }
291+ group. addTask {
292+ @Dependency ( \. github. fetchReadme) var fetchReadme
293+ return . readme( await fetchReadme ( owner, repository) )
294+ }
284295
285- do {
286- return try await ( metadata, license, readme)
296+ var results = [ FetchResult] ( )
297+ for try await result in group {
298+ results. append ( result)
299+ }
300+ return results
301+ }
302+
303+ var metadata : Github . Metadata ?
304+ var license : Github . License ?
305+ var readme : Github . Readme ?
306+ for res in results {
307+ switch res {
308+ case . metadata( let data) :
309+ metadata = data
310+ case . license( let data) :
311+ license = data
312+ case . readme( let data) :
313+ readme = data
314+ }
315+ }
316+
317+ guard let metadata = metadata else {
318+ struct MetadataIsNil : Swift . Error { }
319+ throw Github . Error. unexpectedError ( MetadataIsNil ( ) )
320+ }
321+
322+ return ( metadata, license, readme)
287323 } catch let error as Github . Error {
288324 throw error
289325 } catch {
290326 // This whole do { ... } catch { ... } should be unnecessary - it's a workaround for
291327 // https://github.com/swiftlang/swift/issues/76169
292- assert ( false , " Unexpected error type: \( type ( of: error) ) " )
293- // We need to throw _something_ here (we should never hit this codepath though)
328+ assert ( false , " Unexpected error type: \( type ( of: error) ) " )
329+ // We need to throw _something_ here (we should never hit this codepath though)
294330 throw Github . Error. unexpectedError ( error)
295- // We could theoretically avoid this whole second catch and just do
296- // error as! GithubError
297- // but let's play it safe and not risk a server crash, unlikely as it may be.
331+ // We could theoretically avoid this whole second catch and just do
332+ // error as! GithubError
333+ // but let's play it safe and not risk a server crash, unlikely as it may be.
298334 }
299335 }
300336
0 commit comments