我正在使用grpc-swift和ClientInterceptor
向请求添加一个auth令牌。我为send
实现了delegate方法,如下所示
override func send(_ part: GRPCClientRequestPart<Request>, promise: EventLoopPromise<()>?, context: ClientInterceptorContext<Request, Response>) {
guard case .metadata(var headers) = part else {
return context.send(part, promise: promise)
}
let p = context.eventLoop.makePromise(of: String.self)
p.completeWithTask {
"My Token" // In reality this is actually an async function like `await myActor.idToken`
}
p.futureResult.whenSuccess { token in
print(context.eventLoop.inEventLoop) // This returns `true`
headers.add(name: "Authorization", value: "Bearer \(token)")
context.send(.metadata(headers), promise: promise)
}
}
我需要从actor
中读取值,这需要async/await
来获取值,因此使用了创建一个promise,然后是p.completeWithTask
。
我面临的问题是,当这样做,然后调用context.send(_,promise:)
是,我收到一个错误回来说Invalid state: unable to write message
,在看文档,它说/// An invalid state was encountered. This is a serious implementation error.
,我显然做了一些非常错误的,但对我的生活,我不知道是什么?
如果没有promise/future使用它,一切都很好。我不确定我是否正确使用了p.completeWithTask
和p.futureResult.whenSuccess
?
1条答案
按热度按时间plupiseo1#
我很确定你最后会重新排序信息。通常,gRPC请求/响应将是
.metadata(...)
,然后是.message(...)
,最后是.end
。顺序很重要。如果你不服从正确的命令,你就会进入非法状态。因此,您可能会遇到以下情况:
1.你收到一个
.metadata(...)
,你没有立即转发,因为你异步获得了auth令牌1.您收到
.message(...)
并立即转发1.(无关紧要,因为我们已经处于糟糕的状态)您完成了异步身份验证并转发了增强的
.metadata(...)
你看现在是什么情况?您可能会在 *
.metadata
之前转发.message
*,这是非法的,会使您进入该状态。那你怎么解决这个问题呢?我认为你需要手动缓冲所有你收到的
part
,直到你设法得到增强的.metadata(...)
。这不是难以置信的困难,但也有点烦人。这个问题与你正在做的事情非常相似顺便说一句:https://github.com/grpc/grpc-swift/issues/1181
特别是@glbrntt回复中的这段
您还必须确保在拦截器中适当地缓冲了所有请求部分,以确保请求部分以正确的顺序发送(即:您可以在获取令牌的异步代码完成之前接收要发送的请求消息)。
我在gRPC Swift上提交了一些关于这个的bug: