我有一个异步存根,其中添加了一个观察者:
val obs = object: StreamObserver<Hallo> {
override fun onNext(value: Hallo) {
streamSuccess(value)
}
override fun onError(t: Throwable?) {
nonSuccess(t?.message ?: "Unknow error")
}
override fun onCompleted() {
Log.d("Info", "completed")
completed()
}
}
我希望a能够从异步存根中删除该观察者,因此可以取消客户端的流式传输。
如github问题中所述:https://github.com/grpc/grpc-java/issues/3095
我尝试保留观察者的局部变量,以便客户端稍后可以执行:
observer?.onError(Status.CANCELLED.cause)
那没有用。
我也尝试从抽象类创建自己的类:ClientCallStreamObserver
class CancellableStreamObserver<TResponse>(val next:(value:TResponse)->Unit, val onError:(t:Throwable)-> Unit, val onCompleted:(()->Unit), val onCanceledHandler: (()->Unit)? = null) : ClientCallStreamObserver<TResponse>() {
override fun isReady(): Boolean {
return true
}
override fun setOnReadyHandler(onReadyHandler: Runnable?) {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun disableAutoInboundFlowControl() {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun cancel(message: String?, cause: Throwable?) {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun request(count: Int) {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun setMessageCompression(enable: Boolean) {
//TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onNext(value: TResponse) {
next(value)
}
override fun onError(t: Throwable) {
if (t is StatusException) {
if (t.status.code == Status.Code.CANCELLED) {
onCanceledHandler?.let {
it()
}
}
}
if (t is StatusRuntimeException) {
if (t.status.code == Status.Code.CANCELLED) {
onCanceledHandler?.let {
it()
}
}
}
this.onError(t)
}
override fun onCompleted() {
onCompleted()
}
}
所以以后我可以打电话给
observer?.cancel("Cancelled for the user",Status.CANCELLED.cause)
那也不起作用。
我知道它没有用,这是因为如果用户再次添加新的观察者,我会得到重复的响应,就像旧的观察者还活着一样。
我知道我可以使用channel.shutdownNow()
关闭频道。但是我认为这太激进了。
谢谢
答案 0 :(得分:1)
从引用的https://github.com/grpc/grpc-java/issues/3095:
对于异步,您可以通过将返回的 StreamObserver强制转换为ClientCallStreamObserver或实现让传入的StreamObserver实现ClientResponseObserver来使用ClientCallStreamObserver.cancel()。
(添加了重点)
grpc-java将实现适当的方法,而不是您的实例。因此模式将是:
stub.foo(req, object: ClientResponseObserver<Hallo> {
override fun beforeStart(respObs: ClientCallStreamObserver<Hallo>) {
// save respObs for later
}
override fun onNext(value: Hallo) {
streamSuccess(value)
}
override fun onError(t: Throwable?) {
nonSuccess(t?.message ?: "Unknow error")
}
override fun onCompleted() {
Log.d("Info", "completed")
completed()
}
});
// -or- (for streaming calls only)
val obs = ...;
val respObs = stub.foo(obs) as (ClientCallStreamObserver<Hallo>);
respObs.onNext(req);
// save respObs for later
请注意,两种情况下的respObs
都是相同的。使用ClientResponseObserver
主要用于有流媒体并且想要在响应观察器中取消以避免线程竞争的情况。