Skip to content

Commit

Permalink
Constrained Result to be Sendable from the new executeThenClose.
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelcepeda committed Feb 28, 2025
1 parent 07d9dd2 commit 601a89d
Showing 1 changed file with 33 additions and 4 deletions.
37 changes: 33 additions & 4 deletions Sources/NIOCore/AsyncChannel/AsyncChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ public struct NIOAsyncChannel<Inbound: Sendable, Outbound: Sendable>: Sendable {
isolatedTo actor: isolated (any Actor)? = #isolation,
_ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>, _ outbound: NIOAsyncChannelOutboundWriter<Outbound>)
async throws -> Result
) async throws -> Result {
) async throws -> Result where Result: Sendable {
let result: Result
do {
result = try await body(self._inbound, self._outbound)
Expand Down Expand Up @@ -385,9 +385,38 @@ extension NIOAsyncChannel {
public func executeThenClose<Result>(
_ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>) async throws -> Result
) async throws -> Result where Outbound == Never {
try await self.executeThenClose { inbound, _ in
try await body(inbound)
let result: Result
do {
result = try await body(self._inbound)
} catch let bodyError {
do {
self._outbound.finish()
try await self.channel.close().get()
throw bodyError
} catch {
throw bodyError
}
}

self._outbound.finish()
// We ignore errors from close, since all we care about is that the channel has been closed
// at this point.
self.channel.close(promise: nil)
// `closeFuture` should never be failed, so we could ignore the error. However, do an
// assertionFailure to guide bad Channel implementations that are incorrectly failing this
// future to stop failing it.
do {
try await self.channel.closeFuture.get()
} catch {
assertionFailure(
"""
The channel's closeFuture should never be failed, but it was failed with error: \(error).
This is an error in the channel's implementation.
Refer to `Channel/closeFuture`'s documentation for more information.
"""
)
}
return result
}

#if compiler(>=6.0)
Expand All @@ -401,7 +430,7 @@ extension NIOAsyncChannel {
public func executeThenClose<Result>(
isolatedTo actor: isolated (any Actor)? = #isolation,
_ body: (_ inbound: NIOAsyncChannelInboundStream<Inbound>) async throws -> Result
) async throws -> Result where Outbound == Never {
) async throws -> Result where Outbound == Never, Result: Sendable {
try await self.executeThenClose { inbound, _ in
try await body(inbound)
}
Expand Down

0 comments on commit 601a89d

Please sign in to comment.