При написании функции StreamClientInterceptor, как лучше всего определить, когда вызывающая сторона завершает работу? ПКР? Это достаточно просто с унарными перехватчиками или на стороне сервера, где вам передается обработчик., который выполняет RPC, но неясно, как лучше всего сделать это на стороне клиента, когда вы возвращаете ClientStream, с которым затем взаимодействует инициатор.
Одним из вариантов использования для этого является инструментирование OpenTracing, где цель состоит в том, чтобы начать и закончить интервал, чтобы отметить начало и конец RPC.
Стратегия, которую я изучаю, заключается в том, чтобы перехватчик потока возвращал оформленный ClientStream. Этот новый ClientStream считает RPC завершенным, если какой-либо из методов интерфейса Header
, CloseSend
, SendMsg
, RecvMsg
возвращает ошибку или если Context
отменяется. Кроме того, он добавляет эту логику к 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
(см. Вы должны вызывать Recv, пока не получите io.EOF при взаимодействии с grpc.ClientStreams?), поэтому он не будет работать во всех случаях. Есть ли лучший способ сделать это?