i’m trying to adopt the new closure-based SwiftNIO APIs introduced in 2.62.0 and i’m really frustrated with how poorly they compose with TaskGroup.
the main issue with TaskGroup is it does not support rethrows from the closure body, which means you can’t call any throws-colored functions such as NIOAsyncChannel.executeThenClose(_:) without wrapping it in a do block to juggle the error out of the task group.
why not use ThrowingTaskGroup instead? well, ThrowingTaskGroup is an AsyncSequence, and that means as soon as one of the child tasks throws an error, the task group enters a terminal state. this is not what i want here; i want to iterate over an asynchronous sequence of Result<T, any Error> where failed child tasks are expected and tolerated.
what i would really want is to have something in between a TaskGroup and a ThrowingTaskGroup, that supports throwing errors from the task group closure, but forbids errors to be thrown from inside the child tasks themselves.
i’ve found in the past that when people start adding general purpose extensions to fundamental types like Result, you inevitably want to start using them in more than one module. so every project that does this eventually grows a _Core or _Common or _Basics or _Utilities module that becomes a magnet for miscellaneous “convenience” API (Collection.onlyElement, BidirectionalCollection.dropLast(while:), unreachable, log(_:), Double.format(places:), etc.).
and if you maintain more than one repository, it is highly probable that this module will metastasize into a swift-core-utils package that becomes a Universal Dependency and continue accumulating helpful extensions until you have reinvented Foundation.
anyway, that’s not specific to the issue at hand, just a general explanation of why i tend to recommend against adding generic helpers to standard library types.
I run into this myself as well. I ended up using Result but the do/catch dance is quite annoying. You can add an async Result(catching:) overload but that should just be reasync in my personal opinion. We aren't likely getting reasync though so this isn't a real option.