Repository: vapor/vapor
File: Sources/Vapor/Request/Request+BodyStream.swift (Swift)

Code before:
        private(set) var isClosed: Bool
        private let lock = NIOLock()
        private var handler: ((BodyStreamResult, EventLoopPromise<Void>?) -> ())?
        private var buffer: [(BodyStreamResult, EventLoopPromise<Void>?)]
        private let allocator: ByteBufferAllocator

        init(on eventLoop: EventLoop, byteBufferAllocator: ByteBufferAllocator) {
            self.eventLoop = eventLoop
            self.isClosed = false
            self.buffer = []
            self.allocator = byteBufferAllocator
        }

        func read(_ handler: @escaping (BodyStreamResult, EventLoopPromise<Void>?) -> ()) {
            self.handler = handler
            for (result, promise) in self.buffer {
                handler(result, promise)
            }
            self.buffer = []
        }

        func write(_ chunk: BodyStreamResult, promise: EventLoopPromise<Void>?) {
            // See https://github.com/vapor/vapor/issues/2906
            if self.eventLoop.inEventLoop {
                write0(chunk, promise: promise)
            } else {
                self.eventLoop.execute {
                    self.write0(chunk, promise: promise)
                }
            }
        }
        
        private func write0(_ chunk: BodyStreamResult, promise: EventLoopPromise<Void>?) {
            switch chunk {
            case .end, .error:
                self.isClosed = true
            case .buffer: break
            }
            
            if let handler = self.handler {
                handler(chunk, promise)
                // remove reference to handler
                switch chunk {
                case .end, .error:
                    self.handler = nil
                default: break
                }
            } else {
                self.buffer.append((chunk, promise))
            }
        }

Review comment (suggestion):
It is my understanding that `EventLoop.execute(_:)` already does the "is in event loop" check internally, which in addition, can return false negatives in the normal course of execution - If the problem is that you were executing on the event loop unconditionally before and are skipping the extra "hop", this isn't a guaranteed solution.

Code after:
        private(set) var isClosed: Bool
        private var handler: ((BodyStreamResult, EventLoopPromise<Void>?) -> ())?
        private var buffer: [(BodyStreamResult, EventLoopPromise<Void>?)]
        private let allocator: ByteBufferAllocator

        init(on eventLoop: EventLoop, byteBufferAllocator: ByteBufferAllocator) {
            self.eventLoop = eventLoop
            self.isClosed = false
            self.buffer = []
            self.allocator = byteBufferAllocator
        }

        func read(_ handler: @escaping (BodyStreamResult, EventLoopPromise<Void>?) -> ()) {
            self.handler = handler
            for (result, promise) in self.buffer {
                handler(result, promise)
            }
            self.buffer = []
        }

        func write(_ chunk: BodyStreamResult, promise: EventLoopPromise<Void>?) {
            // See https://github.com/vapor/vapor/issues/2906
            if self.eventLoop.inEventLoop {
                write0(chunk, promise: promise)
            } else {
                self.eventLoop.execute {
                    self.write0(chunk, promise: promise)
                }
            }
        }
        
        private func write0(_ chunk: BodyStreamResult, promise: EventLoopPromise<Void>?) {
            switch chunk {
            case .end, .error:
                self.isClosed = true
            case .buffer: break
            }
            
            if let handler = self.handler {
                handler(chunk, promise)
                // remove reference to handler
                switch chunk {
                case .end, .error:
                    self.handler = nil
                default: break
                }
            } else {
                self.buffer.append((chunk, promise))
            }
        }