Repository: apple/swift-nio
File: Sources/NIOCore/AsyncChannel/AsyncChannel.swift (Swift)

Code before:
    /// The writer for writing outbound messages.
    @available(*, deprecated, message: "Use the executeThenClose scoped method instead.")
    public var outbound: NIOAsyncChannelOutboundWriter<Outbound> {
        self._outbound
    }

    @usableFromInline
    let _inbound: NIOAsyncChannelInboundStream<Inbound>
    @usableFromInline
    let _outbound: NIOAsyncChannelOutboundWriter<Outbound>

    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel``.
    ///
    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because
    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.
    ///
    /// - Parameters:
    ///   - channel: The ``Channel`` to wrap.
    ///   - configuration: The ``NIOAsyncChannel``s configuration.
    ///   - closeOnDeinit: Indicates if the underlying channel should be closed once the `inbound` and `outbound` have been deinited. We do not recommend to rely on
    ///   deinit based resource tear down.
    @inlinable
    public init(
        synchronouslyWrapping channel: Channel,
        configuration: Configuration = .init(),
        closeOnDeinit: Bool
    ) throws {
        channel.eventLoop.preconditionInEventLoop()
        self.channel = channel
        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(
            backPressureStrategy: configuration.backPressureStrategy,
            isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled,
            closeOnDeinit: closeOnDeinit
        )
    }

    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel`` where the outbound type is `Never`.
    ///
    /// This initializer will finish the ``NIOAsyncChannel/outbound`` immediately.
    ///
    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because
    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.
    ///
    /// - Parameters:
    ///   - channel: The ``Channel`` to wrap.
    ///   - configuration: The ``NIOAsyncChannel``s configuration.
    ///   - closeOnDeinit: Indicates if the underlying channel should be closed once the `inbound` and `outbound` have been deinited. We do not recommend to rely on
    ///   deinit based resource tear down.
    @inlinable
    public init(
        synchronouslyWrapping channel: Channel,

Review comment (refactor):
It's a shame we have to rely on users setting this to get the right behaviour because they can still set this to be `true` and get the old behaviour without a deprecation warning.

Ideally users shouldn't have to think about this and we would have two differently spelled `init`s, the deprecated old one and the new no-close-on-deinit one. That'd make it obvious which one to call. 


I'm not sure what to suggest for naming here, however. A couple of ideas (don't love either):
- a `static` helper `static func synchronouslyWrapping(_:configuration:) -> Self`
- `init(wrappingChannelSynchronously:configuration:)`

Code after:
    /// The writer for writing outbound messages.
    @available(*, deprecated, message: "Use the executeThenClose scoped method instead.")
    public var outbound: NIOAsyncChannelOutboundWriter<Outbound> {
        self._outbound
    }

    @usableFromInline
    let _inbound: NIOAsyncChannelInboundStream<Inbound>
    @usableFromInline
    let _outbound: NIOAsyncChannelOutboundWriter<Outbound>

    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel``.
    ///
    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because
    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.
    ///
    /// - Parameters:
    ///   - channel: The ``Channel`` to wrap.
    ///   - configuration: The ``NIOAsyncChannel``s configuration.
    @inlinable
    public init(
        wrappingChannelSynchronously channel: Channel,
        configuration: Configuration = .init()
    ) throws {
        channel.eventLoop.preconditionInEventLoop()
        self.channel = channel
        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(
            backPressureStrategy: configuration.backPressureStrategy,
            isOutboundHalfClosureEnabled: configuration.isOutboundHalfClosureEnabled,
            closeOnDeinit: false
        )
    }

    /// Initializes a new ``NIOAsyncChannel`` wrapping a ``Channel`` where the outbound type is `Never`.
    ///
    /// This initializer will finish the ``NIOAsyncChannel/outbound`` immediately.
    ///
    /// - Important: This **must** be called on the channel's event loop otherwise this init will crash. This is necessary because
    /// we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.
    ///
    /// - Parameters:
    ///   - channel: The ``Channel`` to wrap.
    ///   - configuration: The ``NIOAsyncChannel``s configuration.
    @inlinable
    public init(
        wrappingChannelSynchronously channel: Channel,
        configuration: Configuration = .init()
    ) throws where Outbound == Never {
        channel.eventLoop.preconditionInEventLoop()
        self.channel = channel
        (self._inbound, self._outbound) = try channel._syncAddAsyncHandlers(