[ https://issues.apache.org/jira/browse/KUDU-2065?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16082806#comment-16082806 ]
Michael Ho commented on KUDU-2065: ---------------------------------- cc'ing [~dhecht], [~henryr] and [~sailesh] > Support cancellation for outbound client RPC > -------------------------------------------- > > Key: KUDU-2065 > URL: https://issues.apache.org/jira/browse/KUDU-2065 > Project: Kudu > Issue Type: Improvement > Components: rpc > Reporter: Michael Ho > Priority: Minor > > Currently, there is no way to cancel an outbound client RPC call in Kudu. The > following is a proposal to do so. Please feel free to comment on it. > A new interface {{void RpcController::Cancel()}} will be introduced. It > enqueues a reactor task which will eventually call {{void > OutboundCall::Cancel()}}. A new RpcFeature flag {{CANCELLABLE}} will be added > to indicate whether the server can handle in-flight RPC which is cancelled. > More details below. A client can specify whether such functionality > is needed by setting a bool flag in {{RpcController}} passed to the proxy. > Depending on the state of an OutboundCall, cancellation will happen as > follows: > * READY > ** it hasn't been scheduled yet. Set the cancellation flag in the > OutboundCall object. When it's eventually scheduled by > {{Connection::QueueOutboundCall()}}, it will check the cancellation flag > before assigining a {{call_id}}. If it's set, call > {{OutboundCall::SetCancelled()}} and return. > * ON_OUTBOUND_QUEUE > ** it's on the outbound transfer queue but transfer hasn't started yet. > {{Connection::WriteHandler()}} will check the cancellation flag before > initiating a transfer. If it's set, the transfer will be popped from the > queue and deleted. Call {{OutboundCall::SetCancelled()}} and return. > * SENDING > ** some of the payload has already made its way to the other side. To make > sure the outbound call doesn't hold on to {{sidecars_}} till the end of the > transfer, the outbound call needs to clear {{sidecars_}} and sends the > remaining bytes as 0. The entry in CAR map will be removed and > {{OutboundCall::SetCancelled()}} will be invoked. Please see below on how the > server will handle this incomplete RPC message. > * SENT > ** The payload has been sent. Waiting for a response. Call > {{OutboundCall::SetCancelled()}}. Incoming response will be dropped on the > floor. > * NEGOTIATION_TIMED_OUT > * TIMED_OUT > * CANCELLED > * FINISHED_NEGOTIATION_ERROR > * FINISHED_ERROR > * FINISHED_SUCCESS > ** No-op. Callback has been invoked already. > {{OutboundCall::SetCancelled()}} will mark {{status_}} to {{Cancelled}}. Set > the state to {{CANCELLED}}. In addition, it will clear {{side_cars_}}, delete > {{header_buf_}} and invoke the callback. > When an OutboundCall already in the {{SENDING}} state is cancelled, > {{sidecars_}} will be cleared. This provides guarantee to the RPC client that > the RPC subsystem doesn't have any reference left to payload pointed by > {{sidecars_}} so the RPC client can safely free them if it's passed in as a > SliceSideCar. It's freed immediately if it's passed in as FastStringSideCar. > An in-flight RPC will be cancelled by sending the remainder of the payload > (encoded in total message length) as 0. An optional bool field is added to > the request header. If it's set, it's expected that a single byte at the end > which is 1 if the payload has been cancelled when it was in-flight. > Potentially, we can do the same treatment for client RPC which times out > already. > {noformat} > +------------------------------------------------+ > | Total message length (4 bytes) | > +------------------------------------------------+ > | RPC Header protobuf length (variable encoding) | > +------------------------------------------------+ > | RPC Header protobuf | > +------------------------------------------------+ > | Main message length (variable encoding) | > +------------------------------------------------+ --- 0 > | Main message protobuf | > +------------------------------------------------+ --- sidecar_offsets(0) > | Sidecar 0 | > +------------------------------------------------+ --- sidecar_offsets(1) > | Sidecar 1 | > +------------------------------------------------+ --- sidecar_offsets(2) > | Sidecar 2 | > +------------------------------------------------+ --- ... > | ... | > +------------------------------------------------+ > | cancelled | -- true if RPC has been > cancelled mid-flight > +------------------------------------------------+ > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)