Skip to content

Commit dd40215

Browse files
FranzBuschLukasa
andauthored
Implement a back-pressure aware AsyncSequence source (#2230)
* Implement a back-pressure aware `AsyncSequence` source # Motivation We ran into multiple use-cases (#2067, https://github.com/grpc/grpc-swift/blob/main/Sources/GRPC/AsyncAwaitSupport/PassthroughMessageSource.swift) already where we want to vend an `AsyncSequence` where elements are produced from the sync world while the consumer is in the async world. Furthermore, we need the `AsyncSequence` to properly support back-pressure. Since we already identified that this is something fundamental for our ecosystem and that current `AsyncSequence` sources are not providing the proper semantics or performance, it would be great to find a single solution that we can use everywhere. Before diving into the code, I think it is good to understand the goals of this `AsyncSequence`: - The `AsyncSequence` should support a single unicast `Subscriber` - The `AsyncSequence` should allow a pluggable back-pressure strategy - The `AsyncSequence` should allow to yield a sequence of elements to avoid aquiring the lock for every element. - We should make sure to do as few thread hops as possible to signal the producer to demand more elements. # Modification This PR introduces a new `AsyncSequence` called `NIOBackPressuredAsyncSequence`. The goal of that sequence to enable sync to async element streaming with back-pressure support. # Result We can now power our sync to async use-cases with this new `AsyncSequence`. # Future work There are couple of things left that I wanna land in a follow up PR: 1. An adaptive back-pressure strategy that grows and shrinks depending on the speed of consumption 2. A throwing version of this sequence 3. Potentially an async version that suspends on `yield()` and resumes when more elements should be demanded. * Fix cancellation handling * Review * Add init helper * Add return types to help the type checker * Fix 5.7 CI * Rename delegate method and update docs * Review * Switch to Deque, rename the type and change the behaviour of yielding an empty sequence * Review comments from George * Review comments by Konrad * Review and add tests for the high low strategy * Fix 5.4 tests * Code review Co-authored-by: Cory Benfield <[email protected]>
1 parent b4e0a27 commit dd40215

File tree

5 files changed

+1740
-1
lines changed

5 files changed

+1740
-1
lines changed

Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
import PackageDescription
1717

1818
let swiftAtomics: PackageDescription.Target.Dependency = .product(name: "Atomics", package: "swift-atomics")
19+
let swiftCollections: PackageDescription.Target.Dependency = .product(name: "DequeModule", package: "swift-collections")
1920

2021
var targets: [PackageDescription.Target] = [
2122
.target(name: "NIOCore",
22-
dependencies: ["NIOConcurrencyHelpers", "CNIOLinux", "CNIOWindows"]),
23+
dependencies: ["NIOConcurrencyHelpers", "CNIOLinux", "CNIOWindows", swiftCollections]),
2324
.target(name: "_NIODataStructures"),
2425
.target(name: "NIOEmbedded",
2526
dependencies: ["NIOCore",
@@ -140,6 +141,7 @@ let package = Package(
140141
],
141142
dependencies: [
142143
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"),
144+
.package(url: "https://github.com/apple/swift-collections.git", from: "1.0.2"),
143145
],
144146
targets: targets
145147
)

0 commit comments

Comments
 (0)