Skip to content

Commit

Permalink
Add configuration for NIOAsyncChannel (#2464)
Browse files Browse the repository at this point in the history
# Motivation
While adopting the new `NIOAsyncChannel` type we saw an exploding number of parameters passed to the various connect/bind/configure methods. All these methods had in common that we had to pass configuration for the `NIOAsyncChannel`.

# Modification
This PR introduces a new type `NIOAsyncChannel.Configuration` which groups all four configuration parameters into a struct.

# Result
We can now write more concise methods that use a single configuration object.
  • Loading branch information
FranzBusch authored Jul 11, 2023
1 parent 7e6dc1e commit 5f54289
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 322 deletions.
67 changes: 46 additions & 21 deletions Sources/NIOCore/AsyncChannel/AsyncChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,43 @@
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@_spi(AsyncChannel)
public final class NIOAsyncChannel<Inbound: Sendable, Outbound: Sendable>: Sendable {
@_spi(AsyncChannel)
public struct Configuration {
/// The backpressure strategy of the ``NIOAsyncChannel/inboundStream``.
public var backpressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark

/// If outbound half closure should be enabled. Outbound half closure is triggered once
/// the ``NIOAsyncChannelWriter`` is either finished or deinitialized.
public var isOutboundHalfClosureEnabled: Bool

/// The ``NIOAsyncChannel/inboundStream`` message's type.
public var inboundType: Inbound.Type

/// The ``NIOAsyncChannel/outboundWriter`` message's type.
public var outboundType: Outbound.Type

/// Initializes a new ``NIOAsyncChannel/Configuration``.
///
/// - Parameters:
/// - backpressureStrategy: The backpressure strategy of the ``NIOAsyncChannel/inboundStream``. Defaults
/// to a watermarked strategy (lowWatermark: 2, highWatermark: 10).
/// - isOutboundHalfClosureEnabled: If outbound half closure should be enabled. Outbound half closure is triggered once
/// the ``NIOAsyncChannelWriter`` is either finished or deinitialized. Defaults to `false`.
/// - inboundType: The ``NIOAsyncChannel/inboundStream`` message's type.
/// - outboundType: The ``NIOAsyncChannel/outboundWriter`` message's type.
public init(
backpressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark = .init(lowWatermark: 2, highWatermark: 10),
isOutboundHalfClosureEnabled: Bool = false,
inboundType: Inbound.Type = Inbound.self,
outboundType: Outbound.Type = Outbound.self
) {
self.backpressureStrategy = backpressureStrategy
self.isOutboundHalfClosureEnabled = isOutboundHalfClosureEnabled
self.inboundType = inboundType
self.outboundType = outboundType
}
}

/// The underlying channel being wrapped by this ``NIOAsyncChannel``.
@_spi(AsyncChannel)
public let channel: Channel
Expand All @@ -52,25 +89,18 @@ public final class NIOAsyncChannel<Inbound: Sendable, Outbound: Sendable>: Senda
///
/// - Parameters:
/// - channel: The ``Channel`` to wrap.
/// - backpressureStrategy: The backpressure strategy of the ``NIOAsyncChannel/inboundStream``.
/// - isOutboundHalfClosureEnabled: If outbound half closure should be enabled. Outbound half closure is triggered once
/// the ``NIOAsyncChannelWriter`` is either finished or deinitialized.
/// - inboundType: The ``NIOAsyncChannel/inboundStream`` message's type.
/// - outboundType: The ``NIOAsyncChannel/outboundWriter`` message's type.
/// - configuration: The ``NIOAsyncChannel``s configuration.
@inlinable
@_spi(AsyncChannel)
public init(
synchronouslyWrapping channel: Channel,
backpressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,
isOutboundHalfClosureEnabled: Bool = false,
inboundType: Inbound.Type = Inbound.self,
outboundType: Outbound.Type = Outbound.self
configuration: Configuration = .init()
) throws {
channel.eventLoop.preconditionInEventLoop()
self.channel = channel
(self.inboundStream, self.outboundWriter) = try channel._syncAddAsyncHandlers(
backpressureStrategy: backpressureStrategy,
isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled
backpressureStrategy: configuration.backpressureStrategy,
isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled
)
}

Expand All @@ -83,23 +113,18 @@ public final class NIOAsyncChannel<Inbound: Sendable, Outbound: Sendable>: Senda
///
/// - Parameters:
/// - channel: The ``Channel`` to wrap.
/// - backpressureStrategy: The backpressure strategy of the ``NIOAsyncChannel/inboundStream``.
/// - isOutboundHalfClosureEnabled: If outbound half closure should be enabled. Outbound half closure is triggered once
/// the ``NIOAsyncChannelWriter`` is either finished or deinitialized.
/// - inboundType: The ``NIOAsyncChannel/inboundStream`` message's type.
/// - configuration: The ``NIOAsyncChannel``s configuration.
@inlinable
@_spi(AsyncChannel)
public init(
synchronouslyWrapping channel: Channel,
backpressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,
isOutboundHalfClosureEnabled: Bool = false,
inboundType: Inbound.Type = Inbound.self
configuration: Configuration
) throws where Outbound == Never {
channel.eventLoop.preconditionInEventLoop()
self.channel = channel
(self.inboundStream, self.outboundWriter) = try channel._syncAddAsyncHandlers(
backpressureStrategy: backpressureStrategy,
isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled
backpressureStrategy: configuration.backpressureStrategy,
isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled
)

self.outboundWriter.finish()
Expand All @@ -125,7 +150,7 @@ public final class NIOAsyncChannel<Inbound: Sendable, Outbound: Sendable>: Senda
backpressureStrategy: NIOAsyncSequenceProducerBackPressureStrategies.HighLowWatermark? = nil,
isOutboundHalfClosureEnabled: Bool = false,
channelReadTransformation: @Sendable @escaping (Channel) -> EventLoopFuture<ChannelReadResult>,
postFireChannelReadTransformation: @Sendable @escaping (ChannelReadResult) -> EventLoopFuture<Inbound>
postFireChannelReadTransformation: @Sendable @escaping (ChannelReadResult) -> EventLoopFuture<Inbound>
) throws -> NIOAsyncChannel<Inbound, Outbound> where Outbound == Never {
channel.eventLoop.preconditionInEventLoop()
let (inboundStream, outboundWriter): (NIOAsyncChannelInboundStream<Inbound>, NIOAsyncChannelOutboundWriter<Outbound>) = try channel._syncAddAsyncHandlersWithTransformations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ internal final class NIOAsyncChannelInboundStreamChannelHandler<InboundIn: Senda
static func makeHandlerWithTransformations(
eventLoop: EventLoop,
closeRatchet: CloseRatchet,
channelReadTransformation:@Sendable @escaping (InboundIn) -> EventLoopFuture<ReadTransformationResult>,
channelReadTransformation: @Sendable @escaping (InboundIn) -> EventLoopFuture<ReadTransformationResult>,
postFireChannelReadTransformation: @Sendable @escaping (ReadTransformationResult) -> EventLoopFuture<ProducerElement>
) -> NIOAsyncChannelInboundStreamChannelHandler where InboundIn == Channel {
return .init(
Expand Down
Loading

0 comments on commit 5f54289

Please sign in to comment.