Description
Previous ID | SR-15076 |
Radar | rdar://problem/81980766 |
Original Reporter | @Lukasa |
Type | Improvement |
Additional Detail from JIRA
Votes | 2 |
Component/s | Standard Library |
Labels | Improvement |
Assignee | None |
Priority | Medium |
md5: a8ee54f92c5ada6649ec437f217b0051
Issue Description:
AsyncStream.Continuation.YieldResult
exists in no small part to help implement backpressure. It seems designed to let users respond to slow consumption of a buffered stream.
Unfortunately, it's not really possible to take action based on the return value if you cannot tolerate data loss. In particular, .enqueued(remaining: 0)
is a particularly tricky return value. This value signals that the next call to yield
may return .dropped
.
The problem is that the user of AsyncStream
cannot take any action in the face of this return value. There appears to be no way to wait for this situation to resolve itself. As a result, users are forced to essentially sleep for some period of time and then optimistically try again. This either burns CPU (if we poll too frequently) or increases latency (if we poll too infrequently).
This leaves the only backpressure-aware option on AsyncStream
as the init(unfolding:onCancellation:
model. Unfortunately, this init uses "pull-based" backpressure, where an async
function is called whenever there is space. If the user is holding an AsyncSequence
of their own then they are forced to manually hold the AsyncIterator
in order to implement this.
It would be nice to have a complementary API to the return values of yield
that lets us wait until we can be confident that yielding a value is likely to succeed.