| 518 | |
| 519 | template <typename Request, typename Response> |
| 520 | Future<Response> VolumeManagerProcess::call( |
| 521 | const Service& service, |
| 522 | Future<RPCResult<Response>> (Client::*rpc)(Request), |
| 523 | const Request& request, |
| 524 | const bool retry) // Made immutable in the following mutable lambda. |
| 525 | { |
| 526 | Duration maxBackoff = DEFAULT_RPC_RETRY_BACKOFF_FACTOR; |
| 527 | |
| 528 | return process::loop( |
| 529 | self(), |
| 530 | [=] { |
| 531 | // Make the call to the latest service endpoint. |
| 532 | return serviceManager->getServiceEndpoint(service) |
| 533 | .then(process::defer( |
| 534 | self(), |
| 535 | &VolumeManagerProcess::_call<Request, Response>, |
| 536 | lambda::_1, |
| 537 | rpc, |
| 538 | request)); |
| 539 | }, |
| 540 | [=](const RPCResult<Response>& result) mutable |
| 541 | -> Future<ControlFlow<Response>> { |
| 542 | Option<Duration> backoff = retry |
| 543 | ? maxBackoff * (static_cast<double>(os::random()) / RAND_MAX) |
| 544 | : Option<Duration>::none(); |
| 545 | |
| 546 | maxBackoff = std::min(maxBackoff * 2, DEFAULT_RPC_RETRY_INTERVAL_MAX); |
| 547 | |
| 548 | // We dispatch `__call` for testing purpose. |
| 549 | return process::dispatch( |
| 550 | self(), &VolumeManagerProcess::__call<Response>, result, backoff); |
| 551 | }); |
| 552 | } |
| 553 | |
| 554 | |
| 555 | template <typename Request, typename Response> |