Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the RPC framework so that we can return a Result or a new class AsyncResult from RPC handlers #2637

Closed
mbautin opened this issue Oct 17, 2019 · 1 comment
Assignees

Comments

@mbautin
Copy link
Collaborator

mbautin commented Oct 17, 2019

Currently RPC handlers have to respond to the RPC on all exit paths, leading to utility macros like:

#define VERIFY_RESULT_OR_RETURN(expr) \
  __extension__ ({ \
    auto&& __result = (expr); \
    if (!__result.ok()) { return; } \
    std::move(*__result); \
  })

and templates like

template <class ErrType, typename ErrEnum>
void SetupErrorAndRespond(ErrType* error,
                          const Status& s,
                          ErrEnum code,
                          rpc::RpcContext* context) {
  // Generic "service unavailable" errors will cause the client to retry later.
  if (code == ErrType::UNKNOWN_ERROR && s.IsServiceUnavailable()) {
    context->RespondRpcFailure(rpc::ErrorStatusPB::ERROR_SERVER_TOO_BUSY, s);
    return;
  }

  StatusToPB(s, error->mutable_status());
  error->set_code(code);
  context->RespondSuccess();
}

This makes RPC handling code quite different from the rest of our code where we can just use RETURN_NOT_OK.

@spolitov's idea for changing the framework is to change the RPC handler format from

void TabletServiceImpl::GetTransactionStatus(const GetTransactionStatusRequestPB* req,
                                             GetTransactionStatusResponsePB* resp,
                                             rpc::RpcContext context) {

to

Result<GetTransactionStatusResponsePB> TabletServiceImpl::GetTransactionStatus(const GetTransactionStatusRequestPB& req) {
…
}

or even to

AsyncResult<GetTransactionStatusResponsePB> TabletServiceImpl::GetTransactionStatus(const GetTransactionStatusRequestPB& req, rpc::RpcContext* context) {
…
}

and the handler code from

  if (call->method_name() == "GetTransactionStatus") {
    auto rpc_context = yb_call->IsLocalCall() ?
        ::yb::rpc::RpcContext(
            std::static_pointer_cast<::yb::rpc::LocalYBInboundCall>(yb_call), 
            metrics_[kMetricIndexGetTransactionStatus]) :
        ::yb::rpc::RpcContext(
            yb_call, 
            std::make_shared<GetTransactionStatusRequestPB>(),
            std::make_shared<GetTransactionStatusResponsePB>(),
            metrics_[kMetricIndexGetTransactionStatus]);
    if (!rpc_context.responded()) {
      const auto* req = static_cast<const GetTransactionStatusRequestPB*>(rpc_context.request_pb());
      auto* resp = static_cast<GetTransactionStatusResponsePB*>(rpc_context.response_pb());
      GetTransactionStatus(req, resp, std::move(rpc_context));
    }
    return;
  }

to something like

    if (!rpc_context.responded()) {
      const auto* req = static_cast<const GetTransactionStatusRequestPB*>(rpc_context.request_pb());
      auto resp = GetTransactionStatus(req, &rpc_context);
      switch (resp.type()) {
    case Resp::Failure: rpc_context.RespondFailure(); break;
    case Resp::Success: rpc_context.RespondSuccess(resp.pb()); break;
    case Resp::Async: break; 
    }
@bmatican
Copy link
Contributor

bmatican commented Mar 3, 2022

Done as part of #11205

@bmatican bmatican closed this as completed Mar 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants