maartene
(Maarten Engels)
1
Hi everyone,
So I've been getting code ready for Swift 6 using Strict Concurrency Checking. I solved all the warnings, except for this one:
final class ParseHandler: ChannelInboundHandler, Sendable {
typealias InboundIn = MudCommand
typealias InboundOut = [MudResponse]
public func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let promise = context.eventLoop.makePromise(of: Void.self)
let mudCommand = self.unwrapInboundIn(data)
// `Context` does not conform to `@Sendable`, but `EventLoop` does,
// so we pass only the EventLoop and a reference to the `fireChannelRead` function.
let eventLoop = context.eventLoop
let fireChannelRead = context.fireChannelRead
promise.completeWithTask {
let response = await createMudResponse(mudCommand: mudCommand)
eventLoop.execute {
fireChannelRead(self.wrapInboundOut(response)) // WARNING: Capture of 'fireChannelRead' with non-sendable type '(NIOAny) -> ()' in a `@Sendable` closure
}
}
}
}
What I try to accomplish is this: I have all "business logic" in the Swift concurrency world, hidden behind the createMudResponse function. This async function just returns a result at some time. After this result becomes available, I want to send out the result. I now do this using fireChannelRead. And that leads to this error.
Am I on the right track here? How should I go about this?
KR Maarten
sliemeobn
(Simon Leeb)
2
The "proper" refactoring would probably be utilizing the NIOAsyncChannel further down the pipline to get your logic out of the channel handlers.
As a quick-fix, you could wrap your context or fireChannelRead function in a NIOLoopBound box - should do the trick I think.
2 Likes
maartene
(Maarten Engels)
3
The NIOLoopBound box is indeed the quick fix. 
Now I'm gonna try using NIOAsyncChannel.
1 Like