You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@jclouds.apache.org by 李 煜东 <li...@hotmail.com> on 2019/03/15 13:41:36 UTC

答复: How to set local properties in jclouds?

Hi Andrea,

Thank you for your replying. In my case, I need to set different MAX_RETRIES for specific POST request.

overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, Integer.toString(100)); makes all requests retry for a same number of times.

Could you give me a example on that?

Thanks and best regards,
Yudong
________________________________
发件人: Andrea Turli <an...@gmail.com>
发送时间: 2019年3月15日 18:38
收件人: user@jclouds.apache.org
主题: Re: How to set local properties in jclouds?

Hi Li Yudong,

I think you can do something similar to https://github.com/jclouds/jclouds-examples/blob/master/compute-basics/src/main/java/org/jclouds/examples/compute/basics/MainApp.java#L267

adding something like this to the properties overrides you pass to your Context

overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, Integer.toString(100));

HTH,
Andrea

On Fri, Mar 15, 2019 at 11:21 AM liyudong123@hotmail.com<ma...@hotmail.com> <li...@hotmail.com>> wrote:
Hi,

As jclouds Documentation-Configuration describes, properties can be set before context built. What about local properties for example I'd like to set PROPERTY_MAX_RETRIES for a single command, is that possible?

Thanks
Li Yudong

Re: How to set local properties in jclouds?

Posted by Ignasi Barrera <na...@apache.org>.
It's not directly possible to configure max retries per command, but with a
little bit of code, you can do it.
First, let's create a custom retry handler that will read a custom
configured value for each command. Custom values will be configured via
context properties as follows:

// If the API method has a '@Named' annotation, use the value in the
annoattion to identify the method
overrides.setProperty("jclouds.max-retries.services:list, "5");
// Otherqise use the fully qualified class name
overrides.setProperty("jclouds.max-retries.org.jclouds.foo.bar.ApiClassName,
"10");

Then create the handler that will read the custom properties and apply the
configured max retries:

import static com.google.common.base.Optional.fromNullable;import
static com.google.common.collect.Maps.transformValues;import static
org.jclouds.util.Maps2.transformKeys;
import java.io.IOException;import java.util.Map;import java.util.regex.Pattern;
import javax.inject.Inject;
import org.jclouds.http.HttpCommand;import
org.jclouds.http.HttpResponse;import
org.jclouds.http.handlers.BackoffLimitedRetryHandler;import
org.jclouds.rest.config.InvocationConfig;import
org.jclouds.rest.internal.GeneratedHttpRequest;import
org.jclouds.util.Predicates2;
import com.google.common.base.Function;import
com.google.common.base.Optional;import
com.google.common.base.Predicate;
public class CustomRetryHandler extends BackoffLimitedRetryHandler {
   private static final String PREFIX = "jclouds.max-retries.";

   private final InvocationConfig invocationConfig;
   private final Map<String, Integer> retriesPerCommand;

   @Inject
   CustomRetryHandler(InvocationConfig invocationConfig,
Function<Predicate<String>, Map<String, String>> propsFilter) {
      this.invocationConfig = invocationConfig;
      this.retriesPerCommand = maxRetries(propsFilter);
   }

   @Override
   public boolean shouldRetryRequest(HttpCommand command, IOException error) {
      Optional<Integer> customRetry = getMaxRetriesForCommand(command);
      if (!customRetry.isPresent()) {
         return super.shouldRetryRequest(command, error);
      }
      return waitIfNeeded(command, customRetry.get());
   }

  @Override
   public boolean shouldRetryRequest(HttpCommand command, HttpResponse
response) {
     Optional<Integer> customRetry = getMaxRetriesForCommand(command);
      if (!customRetry.isPresent()) {
         return super.shouldRetryRequest(command, response);
      }
      return waitIfNeeded(command, customRetry.get());
   }

   private Optional<Integer> getMaxRetriesForCommand(HttpCommand command)  {
      GeneratedHttpRequest request = (GeneratedHttpRequest)
command.getCurrentRequest();
      String commandName =
invocationConfig.getCommandName(request.getInvocation());
      return fromNullable(retriesPerCommand.get(commandName));
   }

   private boolean waitIfNeeded(HttpCommand command, Integer maxRetries) {
      command.incrementFailureCount();
      if (!command.isReplayable()) {
         logger.error("Cannot retry after server error, command is not
replayable: %1$s", command);
         return false;
      } else if (command.getFailureCount() > maxRetries) {
         logger.error("Cannot retry after server error, command has
exceeded retry limit %1$d: %2$s", maxRetries,
                  command);
         return false;
      } else {
         imposeBackoffExponentialDelay(command.getFailureCount(),
"server error: " + command.toString());
         return true;
      }
   }

   private static Map<String, Integer>
maxRetries(Function<Predicate<String>, Map<String, String>> filter) {
      Map<String, String> retryProps =
filter.apply(Predicates2.startsWith(PREFIX));
      Map<String, Integer> intsByName = transformValues(retryProps,
new Function<String, Integer>() {
         public Integer apply(String input) {
            return Integer.valueOf(String.valueOf(input));
         }
      });
      return transformKeys(intsByName, new Function<String, String>() {
         public String apply(String input) {
            return input.replaceFirst(Pattern.quote(PREFIX), "");
         }
      });
   }
}

Then, configure a Guice module that will set up the custom retry handler:

import org.jclouds.http.HttpRetryHandler;import
org.jclouds.http.annotation.ServerError;import
com.google.inject.AbstractModule;
public class CustomRetriesModule extends AbstractModule {
   @Override
   protected void configure() {
      bind(HttpRetryHandler.class).annotatedWith(ServerError.class).to(CustomRetryHandler.class);
   }
}

And finally, when creating the Context, add that custom module to the list
of modules:

ContextBuilder.NewBuilder(...)
   .overrodes(overrides)
   .modules(ImmutableSet.of(new CustomRetriesModule(), ...)
   ...


HTH!

I.



On Fri, 15 Mar 2019 at 14:44, 李 煜东 <li...@hotmail.com> wrote:

> Hi Andrea,
>
> Thank you for your replying. In my case, I need to set different
> MAX_RETRIES for specific POST request.
>
> overrides.setProperty(Constants.PROPERTY_MAX_RETRIES,
> Integer.toString(100)); makes all requests retry for a same number of
> times.
>
> Could you give me a example on that?
>
> Thanks and best regards,
> Yudong
> ------------------------------
> *发件人:* Andrea Turli <an...@gmail.com>
> *发送时间:* 2019年3月15日 18:38
> *收件人:* user@jclouds.apache.org
> *主题:* Re: How to set local properties in jclouds?
>
> Hi Li Yudong,
>
> I think you can do something similar to
> https://github.com/jclouds/jclouds-examples/blob/master/compute-basics/src/main/java/org/jclouds/examples/compute/basics/MainApp.java#L267
>
> adding something like this to the properties overrides you pass to your
> Context
>
> overrides.setProperty(Constants.PROPERTY_MAX_RETRIES,
> Integer.toString(100));
>
> HTH,
> Andrea
>
> On Fri, Mar 15, 2019 at 11:21 AM liyudong123@hotmail.com <
> liyudong123@hotmail.com> wrote:
>
> Hi,
>
> As jclouds Documentation-Configuration describes, properties can be set
> before context built. What about local properties for example I'd like to
> set PROPERTY_MAX_RETRIES for a single command, is that possible?
>
> Thanks
> Li Yudong
>
>