-
Notifications
You must be signed in to change notification settings - Fork 170
Description
Server APIs commonly have a paging mechanism where the client can fetch one page after another. I am implementing a function that returns an AsyncChannel
representing a stream of pages from a server. It looks like the following:
func allPages() -> AsyncThrowingChannel<Page, Error> {
let channel = AsyncThrowingChannel<Page, Error>()
Task {
do {
var currentPage = try await firstPage()
while true {
await channel.send(currentPage)
guard let nextPage = try await currentPage.nextPage() else {
break
}
currentPage = nextPage
}
channel.finish()
} catch {
channel.fail(error)
}
}
return channel
}
This is a nice abstraction. However, consider the case where the consumer task breaks out of its reader loop early. There is currently no way for the consumer task to indicate to the producer task that it is done with the channel.
@phausler made a related change in #131 to make sure the producer task does not hang when the consumer task is done. However, the producer task still runs to completion, wasting resources.
Instead, I think the send
method should throw CancellatonError
so that the producer task can handle cancellation gracefully.
(CC @jonathanpenn who wrote a related Swift Forums post.)