StreamClientInterceptor関数を記述する場合、インボーカーが RPC を終了するタイミングを判断する最善の方法は何ですか? これは、単項インターセプターまたは RPC を実行するハンドラーが渡されるサーバー側では十分に簡単ですが、呼び出し元が対話するClientStreamを返すクライアント側でこれを行う最善の方法は明確ではありません。.
この使用例の 1 つは、OpenTracing のインストルメント化です。ここでの目標は、RPC の開始と終了をマークするためにスパンを開始および終了することです。
私が検討している戦略は、ストリーム インターセプターが装飾された ClientStream を返すようにすることです。この新しい ClientStream は、インターフェース メソッドHeader、CloseSend、SendMsg、のいずれRecvMsgかがエラーを返した場合、またはContextがキャンセルされた場合に、RPC が完了したと見なします。さらに、このロジックを に追加しますRecvMsg。
func (cs *DecoratedClientStream) RecvMsg(m interface{}) error {
err := cs.ClientStream.RecvMsg(m)
if err == io.EOF {
// Consider the RPC as complete
return err
} else if err != nil {
// Consider the RPC as complete
return err
}
if !cs.isResponseStreaming {
// Consider the RPC as complete
}
return err
}
Recvほとんどの場合はうまくいきますが、私の理解では、結果が次のようになることがわかっている場合、呼び出し元は呼び出す必要はありませんio.EOF( grpc.ClientStreams と対話するときに io.EOF を取得するまで Recv を呼び出す必要はありますか? を参照)。したがって、すべての場合に機能するとは限りません。これを達成するためのより良い方法はありますか?