Tradias / asio-grpc

Asynchronous gRPC with Asio/unified executors
https://tradias.github.io/asio-grpc/
Apache License 2.0
367 stars 34 forks source link

How to modify the hello-world-client-cpp20 example to unblock on timeout or response? #5

Closed rbresalier closed 3 years ago

rbresalier commented 3 years ago

In hello-world-client-cpp20.cpp, how could it be modified to have a timeout getting the response?

Am I correct that the:

co_await agrpc::finish(*reader, response, status);

Would wait indefinitely for a response?

How to make one 'blocking' (actually co_await) call that would resume execution upon either timeout or reception of the response?

Then, how would I know whether it 'unblocked' due to timeout or response reception?

Also, what if the server later sends the response after the timeout? Would it get thrown away or could it get accidentally processed as the response to the next request?

Tradias commented 3 years ago

gRPC provides two ways of handling cancellation of RPCs:

  1. Set a deadline for the entire RPC. In that case, if the deadline is reached during the call to agrpc::finish the grpc::Status will be set to DEADLINE_EXCEEDED. The returned bool will still be true because the call actually made it to the server successfully, see also here.

  2. grpc::ClientContext::TryCancel(). If the cancellation was successful then apgrc::finish's grpc::Status will be set to CANCELLED. You could e.g. have a shorter deadline for an individual RPC step like so:

grpc::Alarm alarm;
agrpc::wait(alarm, std::chrono::system_clock::now() + std::chrono::seconds(1),
            boost::asio::bind_executor(grpc_context,
                                        [&](bool alarm_expired)
                                        {
                                            if (alarm_expired)
                                            {
                                                client_context.TryCancel();
                                            }
                                        }));
co_await agrpc::finish(*reader, response, status);
alarm.Cancel();

and I might be able to get this to work with the new awaitable operators at some point as well. Note that for those to work the grpc::ClientContext would need to be passed to agrpc::finish so that it can be cancelled which is not yet possible.

rbresalier commented 3 years ago

Thanks @Tradias for your answer.

rbresalier commented 3 years ago

@Tradias : Since you are going to update some of the examples based on issue #7 , perhaps you could give an example of setting a deadline timer for one of the rpc calls.

Tradias commented 2 years ago

I have added an example on how to cancel a RPC step. The example is based on a unary RPC which should rather be deadlined with grpc::ClientContext::set_deadline, but it can be applied to streaming RPC steps as well. I leave it as an exercise to you to do that :).

    grpc::ClientContext client_context;
    client_context.set_deadline(std::chrono::system_clock::now() + std::chrono::seconds(5));