У меня следующий случай. Клиент загружает файлы на сервер с помощью потоковой передачи данных (через grpc-dotnet). В некоторых случаях сервер может решить игнорировать клиентский поток и немедленно вернуть ответ. Поскольку клиент не знает о решении сервера, он продолжает вызывать RequestStream.WriteAsync() и в конечном итоге получает Grpc.Core.RpcException: 'Status(StatusCode="OK", Detail="")'
Вопрос: есть ли изящный способ заранее узнать, что вызов уже завершен, без ошибочных попыток записи?
Просматривая исходный код grpc-dotnet, мне удалось найти решение с помощью флага отражения AsyncClientStreamingCall.RequestStream.Call.ResponseFinished, но это выглядит даже хуже, чем обработка исключения с известным кодом состояния.
Псевдокод клиента:
private static async Task CallUploadStream(GrpcService.GrpcServiceClient client)
{
using var streamingCall = client.UploadStream();
// First call
await WriteAsync();
// Delay
await Task.Delay(TimeSpan.FromSeconds(1));
// Second call
await WriteAsync(); // Grpc.Core.RpcException: 'Status(StatusCode="OK", Detail="")'
await streamingCall.RequestStream.CompleteAsync();
await streamingCall;
return;
Task WriteAsync()
{
return streamingCall.RequestStream.WriteAsync(
new UploadStreamRequest
{
Bytes = ByteString.CopyFrom(new byte[1]),
}
);
}
}
Контракт Protobuf:
syntax = "proto3";
package grpc.debug.contract.v1;
option csharp_namespace = "GrpcDebug.Contract";
import "google/protobuf/empty.proto";
service GrpcService {
rpc UploadStream(stream UploadStreamRequest) returns (google.protobuf.Empty);
}
message UploadStreamRequest { bytes bytes = 1; }
Сервер, который немедленно возвращает ответ:
public class GrpcServiceV1 : GrpcService.GrpcServiceBase
{
public override Task UploadStream(IAsyncStreamReader requestStream,
ServerCallContext context)
{
return Task.FromResult(new Empty());
}
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... ted-client