On 10/28/26 17:11, Daniel Sun wrote:
Hi Jochen, Matt,
Thanks for the example and the follow-up.
`defer` for `channel.close()` is still the right cleanup tool, and keeping the
`Awaitable` from `async` so you can `await` it after the `for await` loop
remains the cleanest way I see to surface the producer exception without
inventing `async { } finally { }`.
my example was:
```groovy
def channel = AsyncChannel.create(2)
// send data to channel in another thread
async {
for (int i = 1; i <= 3; i++) {
someCall()
channel.send(i * i)
}
channel.close()
}
// print all values send till the channel closed
for await (value in channel) {
println value
}
```
and the problem was that if someCall() throws an exception we are left
hanging. Yes, if we do not do a free async block this cannot happen, but
then... why do we then allow them at all? Because it makes for short code.
The "Dungeon waves" example on
https://groovy.apache.org/blog/groovy-async-await for example has the
same basic problem. a free async, that will not be able to transport its
exception.
I really think we need to find a solution to this.
bye Jochen