| 297 | /// can be used to inject errors into the RPC. |
| 298 | template <class F, class DebugF, class Request, class Response> |
| 299 | static RpcStatus DoRpcWithRetry(ClientCache<T>* client_cache, TNetworkAddress address, |
| 300 | const F& f, const Request& request, int retries, int64_t delay_ms, |
| 301 | const DebugF& debug_fn, Response* response) { |
| 302 | Status rpc_status; |
| 303 | Status client_status; |
| 304 | |
| 305 | // Try to send the RPC as many times as requested before failing. |
| 306 | for (int i = 0; i < retries; ++i) { |
| 307 | if (i > 0) SleepForMs(delay_ms); // Delay before retrying. |
| 308 | ClientConnection<T> client(client_cache, address, &client_status); |
| 309 | if (!client_status.ok()) continue; |
| 310 | |
| 311 | rpc_status = debug_fn(); |
| 312 | if (!rpc_status.ok()) { |
| 313 | LOG(INFO) << "Injected RPC error to " << TNetworkAddressToString(address) << ": " |
| 314 | << rpc_status.GetDetail(); |
| 315 | continue; |
| 316 | } |
| 317 | |
| 318 | rpc_status = client.DoRpc(f, request, response); |
| 319 | if (rpc_status.ok()) break; |
| 320 | LOG(INFO) << "RPC to " << TNetworkAddressToString(address) << " failed " |
| 321 | << rpc_status.GetDetail(); |
| 322 | } |
| 323 | if (!client_status.ok()) return {client_status, true}; |
| 324 | if (!rpc_status.ok()) return {rpc_status, false}; |
| 325 | return RpcStatus::OK(); |
| 326 | } |
| 327 | |
| 328 | /// In certain cases, the server may take longer to provide an RPC response than |
| 329 | /// the configured socket timeout. Callers may wish to retry receiving the response. |
nothing calls this directly
no test coverage detected