2018年3月10日土曜日

gRPC 非同期メソッドのステータスが取得できるタイミング(前編)

C# の gRPC で、メソッド実行ステータスを安全に取得する方法について調べました。




前回の投稿に続き、GetStatus メソッドを呼び出したときに InvalidOperationException  がスローされる件の調査です。C# です。他の言語での実装は確認していません。


メソッド実行ステータスの取得


gRPC の RPC メソッドには Unary, ServerStreaming, ClientStreaming, DuplexStreaming の 4 つの形態があります。戻り値はそれぞれの形態に応じた非同期呼び出しの制御オブジェクト(以降、call オブジェクトと表します)になります。
※ Unary の同期呼び出しは除きます。

AsyncUnaryCall<TResponse>
= client.UnaryMethod<TRquest, TResponse>(TRequest request);

AsyncServerStreamingCall<TResponse>
= client.ServerStreamingMethod<TRequest, TResponse>(TRequest request);

AsyncClientStreamingCall<TRequest, TResponse>
= client.ClientStreamingMethod<TRequest, TResponse>(TRequest request);

AsyncDuplexStreamingCall<TRequest, TResponse>
= client.DuplexStreamingMethod<TRquest, TResponse>(TRequest request);

call オブジェクトには GetStatus メソッドがあり、ステータスやエラーメッセージを取得することができます。但し、非同期呼び出しの処理が完了していない場合には InvalidOperationException がスローされます。ここで問題になるのが、非同期呼び出しの処理が完了しているかどうかを判定したりコールバックを受け取ったりできるプロパティやメソッドがないということです。call オブジェクトを引数で受け取る汎用メソッドを実装しようとするとこの問題に悩むことになります。


ステータスが取得できるタイミング


以下は DuplexStreaming の一般的なフローです。クライアントからみた「非同期呼び出しの完了」とは、ResponseStream からのデータ読み取りが完了しているかどうかで判断できそうです。

  1. クライアント:RPC メソッドを呼び出す。戻り値として call オブジェクトを取得できる。
  2. クライアント:call オブジェクトの RequestStream の CompleteAsync メソッドを呼び出す。
  3. サーバー:RequestStream からのデータ読み取りが終了する。RPC メソッドの処理を終わらせ、戻り値を返す。
  4. クライアント:call オブジェクトの ResponseStream からのデータ読み取りが終了する。
  5. クライアント:call オブジェクトの GetStatus メソッドでステータスを取得できる。GetTrailers メソッドでトレーラーを取得できる。InvalidOperationException はスローされない。

私はキャンセルやタイムアウトなどステータスを用いた処理を汎用化しようとしています。アプリケーションコードで生成された call オブジェクトがどのような状態であるかがわからない状況で、安全にステータスを取得する方法を考えています。ResponseStream からのデータ読み取りが終了したことを検知できればよく、なんとか実現できそうです。


ResponseHeadersAsync プロパティとの関連性


call オブジェクトには ResponseHeadersAsync プロパティがあります。このプロパティでレスポンスヘッダーが取得できるまで待機すればステータスも取得できそうな印象を受けますが、レスポンスヘッダーとステータスの取得には直接的な関連性はなく、レスポンスヘッダーが取得できてもステータスが取得できないことがありました。gRPC の実装を確認してみましたが、別々のイベントとしてコールバックが処理されているようでした。

ResponseHeadersAsync プロパティは CompleteAsyncm メソッドの呼び出し(上記の2)後であれば待機せずに値を返しますが、この時点では GetStatus メソッドは例外をスローします。


0 件のコメント:

コメントを投稿

paiza のスキルチェックをやってみました

いまさら感はありますが、 paiza のスキルチェックをやってみました。指定された時間内にコードを書いてユニットテストにかけ、その結果を基に評価を数値化してくれるというものですが、ゲーム感覚で空き時間を見つけて進めていこうと考えています。 どうやら時間が短いほど高い評価を得...