code: protected <T> CompletionStage<Optional<T>> doWithServiceImpl(String name, Descriptor.Call<?, ?> serviceCall, Function<URI, CompletionStage<T>> block) {
          return locate(name, serviceCall).thenCompose(uri -> {
            return uri
                    .map(u -> block.apply(u).thenApply(Optional::of))
                    .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty()));
          });
      }
docs: Do the given block with the given service looked up.
  
  This is invoked by {@link #doWithService(String, Descriptor.Call, Function)}, after wrapping the passed in block
  in a circuit breaker if configured to do so.
  
  The default implementation just delegates to the {@link #locate(String, Descriptor.Call)} method, but this method
  can be overridden if the service locator wants to inject other behaviour after the service call is complete.
  
  @param name The service name.
  @param serviceCall The service call that needs the service lookup.
  @param block A block of code that will use the looked up service, typically, to make a call on that service.
  @return A future of the result of the block, if the service lookup was successful.