简体   繁体   English

可重试 grpc-web server-streaming rpc

[英]Retryable grpc-web server-streaming rpc

I am trying to wrap a grpc-web server-streaming client with rxjs.Observable and be able to perform retries if say the server returns an error.我正在尝试用 rxjs.Observable 包装一个 grpc-web 服务器流客户端,如果说服务器返回错误,则能够执行重试。

Consider the following code.考虑以下代码。

  // server
  foo = (call: (call: ServerWritableStream<FooRequest, Empty>): void => {
    if (!call.request?.getMessage()) {
      call.emit("error", { code: StatusCode.FAILED_PRECONDITION, message: "Invalid request" })
    }

    for (let i = 0; i <= 2; i++) {
      call.write(new FooResponse())
    }
    call.end()
  }
 
  // client 
  test("should not end on retry", (done) => {
    new Observable(obs => {
      const call =  new FooClient("http://localhost:8080").foo(new FooRequest())
      call.on("data", data => obs.next(data))
      call.on("error", err => {
        console.log("server emitted error")
        obs.error(err)
      })
      call.on("end", () => {
        console.log("server emitted end")
        obs.complete()
      })
    })
    .pipe(retryWhen(<custom retry policy>))
    .subscribe(
        _resp => () => {},
        _error => {
          console.log("source observable error")
          done()
        },
        () => {
          console.log("source observable completed(?)")
          done()
        })
  })
  
  // output
  server emitted error
  server emitted end
  source observable completed(?)

The server emits the "end" event after(?) emitting "error", so it seems like I have to remove the "end" handler from the source observable.服务器在(?)发出“错误”之后发出“结束”事件,所以我似乎必须从可观察源中删除“结束”处理程序。

What would be an "Rx-y" way to end/complete the stream?结束/完成 stream 的“Rx-y”方式是什么?

For anyone interested, I ended up removing the "end" event handler and replaced it with "status", if the server returns an OK status code (which signals the end of the stream) then the observable is completed.对于任何感兴趣的人,我最终删除了“结束”事件处理程序并将其替换为“状态”,如果服务器返回OK状态代码(表示流结束),则可观察对象完成。

new Observable(obs => {
  const call =  new FooClient("http://localhost:8080").foo(new FooRequest())
  call.on("data", data => obs.next(data))
  call.on("error", err => obs.error(err))
  call.on("status", status: grpcWeb.Status => {
    if (status.code == grpcWeb.StatusCode.OK) {
      return observer.complete()
    }
  })
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM