Skip to content

[SR-15076] AsyncStream.Continuation.YieldResult is hard to use to implement backpressure #57402

Open
@Lukasa

Description

@Lukasa
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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions