Merge pull request #878 from rackspace/compute-configurable-polling

Configurable polling for the ComputeService
This commit is contained in:
Adrian Cole 2012-10-05 10:50:44 -07:00
commit 2f1c215869
6 changed files with 86 additions and 22 deletions

View File

@ -40,6 +40,12 @@ public interface ComputeServiceProperties {
public static final String INIT_STATUS_INITIAL_PERIOD = "jclouds.compute.init-status.initial-period";
public static final String INIT_STATUS_MAX_PERIOD = "jclouds.compute.init-status.max-period";
// The period in milliseconds between node updates when using the ComputeService
public static final String POLL_INITIAL_PERIOD = "jclouds.compute.poll-status.initial-period";
// The max period in milliseconds between node updates when using the ComputeService
public static final String POLL_MAX_PERIOD = "jclouds.compute.poll-status.max-period";
/**
* time in milliseconds to wait for an image to finish creating.
*

View File

@ -39,6 +39,7 @@ import org.jclouds.compute.predicates.AtomicNodeSuspended;
import org.jclouds.compute.predicates.AtomicNodeTerminated;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.predicates.RetryablePredicate;
@ -56,26 +57,35 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
@Provides
@Singleton
@Named(TIMEOUT_NODE_RUNNING)
protected Predicate<AtomicReference<NodeMetadata>> nodeRunning(AtomicNodeRunning statusRunning, Timeouts timeouts) {
return timeouts.nodeRunning == 0 ? statusRunning : new RetryablePredicateGuardingNull<NodeMetadata>(statusRunning,
timeouts.nodeRunning);
protected Predicate<AtomicReference<NodeMetadata>> nodeRunning(
AtomicNodeRunning statusRunning, Timeouts timeouts, PollPeriod period) {
return timeouts.nodeRunning == 0 ?
statusRunning :
new RetryablePredicateGuardingNull<NodeMetadata>(
statusRunning, timeouts.nodeRunning, period.pollInitialPeriod, period.pollMaxPeriod);
}
@Provides
@Singleton
@Named(TIMEOUT_NODE_TERMINATED)
protected Predicate<AtomicReference<NodeMetadata>> serverTerminated(AtomicNodeTerminated statusTerminated, Timeouts timeouts) {
return timeouts.nodeTerminated == 0 ? statusTerminated : new RetryablePredicate<AtomicReference<NodeMetadata>>(statusTerminated,
timeouts.nodeTerminated);
protected Predicate<AtomicReference<NodeMetadata>> serverTerminated(
AtomicNodeTerminated statusTerminated, Timeouts timeouts, PollPeriod period) {
return timeouts.nodeTerminated == 0 ?
statusTerminated :
new RetryablePredicate<AtomicReference<NodeMetadata>>(
statusTerminated, timeouts.nodeTerminated, period.pollInitialPeriod, period.pollMaxPeriod);
}
@Provides
@Singleton
@Named(TIMEOUT_NODE_SUSPENDED)
protected Predicate<AtomicReference<NodeMetadata>> serverSuspended(AtomicNodeSuspended statusSuspended, Timeouts timeouts) {
return timeouts.nodeSuspended == 0 ? statusSuspended : new RetryablePredicateGuardingNull<NodeMetadata>(statusSuspended,
timeouts.nodeSuspended);
protected Predicate<AtomicReference<NodeMetadata>> serverSuspended(
AtomicNodeSuspended statusSuspended, Timeouts timeouts, PollPeriod period) {
return timeouts.nodeSuspended == 0 ?
statusSuspended :
new RetryablePredicateGuardingNull<NodeMetadata>(
statusSuspended, timeouts.nodeSuspended, period.pollInitialPeriod, period.pollMaxPeriod);
}
@Provides
@ -89,17 +99,23 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
@Provides
@Singleton
@Named(TIMEOUT_IMAGE_AVAILABLE)
protected Predicate<AtomicReference<Image>> imageAvailable(AtomicImageAvailable statusAvailable, Timeouts timeouts) {
return timeouts.imageAvailable == 0 ? statusAvailable : new RetryablePredicateGuardingNull<Image>(statusAvailable,
timeouts.imageAvailable);
protected Predicate<AtomicReference<Image>> imageAvailable(
AtomicImageAvailable statusAvailable, Timeouts timeouts, PollPeriod period) {
return timeouts.imageAvailable == 0 ?
statusAvailable :
new RetryablePredicateGuardingNull<Image>(
statusAvailable, timeouts.imageAvailable, period.pollInitialPeriod, period.pollMaxPeriod);
}
@Provides
@Singleton
@Named(TIMEOUT_IMAGE_DELETED)
protected Predicate<AtomicReference<Image>> serverDeleted(AtomicImageDeleted statusDeleted, Timeouts timeouts) {
return timeouts.imageDeleted == 0 ? statusDeleted : new RetryablePredicate<AtomicReference<Image>>(statusDeleted,
timeouts.imageDeleted);
protected Predicate<AtomicReference<Image>> serverDeleted(
AtomicImageDeleted statusDeleted, Timeouts timeouts, PollPeriod period) {
return timeouts.imageDeleted == 0 ?
statusDeleted :
new RetryablePredicate<AtomicReference<Image>>(
statusDeleted, timeouts.imageDeleted, period.pollInitialPeriod, period.pollMaxPeriod);
}
@Override
@ -127,7 +143,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
private final RetryablePredicate<AtomicRefAndOrig> retryablePredicate;
public RetryablePredicateGuardingNull(final Predicate<AtomicReference<T>> predicate, long maxWait) {
public RetryablePredicateGuardingNull(final Predicate<AtomicReference<T>> predicate, long maxWait, long period, long maxPeriod) {
Predicate<AtomicRefAndOrig> nonNullThingPredicate = new Predicate<AtomicRefAndOrig>() {
@Override
public boolean apply(AtomicRefAndOrig input) {
@ -139,7 +155,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
}
}
};
retryablePredicate = new RetryablePredicate<AtomicRefAndOrig>(nonNullThingPredicate, maxWait);
retryablePredicate = new RetryablePredicate<AtomicRefAndOrig>(nonNullThingPredicate, maxWait, period, maxPeriod);
}
@Override

View File

@ -24,6 +24,8 @@ import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_ID;
import static org.jclouds.compute.config.ComputeServiceProperties.IMAGE_LOGIN_USER;
import static org.jclouds.compute.config.ComputeServiceProperties.INIT_STATUS_INITIAL_PERIOD;
import static org.jclouds.compute.config.ComputeServiceProperties.INIT_STATUS_MAX_PERIOD;
import static org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
import static org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
import static org.jclouds.compute.config.ComputeServiceProperties.OS_VERSION_MAP_JSON;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_DELETED;
@ -40,6 +42,7 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.predicates.RetryablePredicate;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
@ -139,6 +142,17 @@ public interface ComputeServiceConstants {
public long initStatusMaxPeriod = 5000;
}
@Singleton
public static class PollPeriod {
@Inject(optional = true)
@Named(POLL_INITIAL_PERIOD)
public long pollInitialPeriod = RetryablePredicate.DEFAULT_PERIOD;
@Inject(optional = true)
@Named(POLL_MAX_PERIOD)
public long pollMaxPeriod = RetryablePredicate.DEFAULT_MAX_PERIOD;
}
@Singleton
public static class ReferenceData {
@Inject(optional = true)

View File

@ -24,6 +24,7 @@ import java.util.Properties;
import org.jclouds.ContextBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants.InitStatusProperties;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.testng.annotations.Test;
/**
@ -51,4 +52,22 @@ public class ComputeServicePropertiesTest {
assertEquals(props.initStatusMaxPeriod, 5001);
}
public void testDefaultPollPeriod() {
PollPeriod props = ContextBuilder.newBuilder("stub").buildInjector()
.getInstance(PollPeriod.class);
assertEquals(props.pollInitialPeriod, 50);
assertEquals(props.pollMaxPeriod, 1000);
}
public void testOverridePollPeriod() {
Properties overrides = new Properties();
overrides.setProperty(ComputeServiceProperties.POLL_INITIAL_PERIOD, "501");
overrides.setProperty(ComputeServiceProperties.POLL_MAX_PERIOD, "5001");
PollPeriod props = ContextBuilder.newBuilder("stub").overrides(overrides).buildInjector()
.getInstance(PollPeriod.class);
assertEquals(props.pollInitialPeriod, 501);
assertEquals(props.pollMaxPeriod, 5001);
}
}

View File

@ -41,6 +41,7 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.TemplateOptionsToStatement;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.AtomicNodeRunning;
import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.util.OpenSocketFinder;
import org.jclouds.scriptbuilder.domain.Statement;
@ -202,6 +203,7 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory = createMock(InitializeRunScriptOnNodeOrPlaceInBadMap.Factory.class);
OpenSocketFinder openSocketFinder = createMock(OpenSocketFinder.class);
Timeouts timeouts = new Timeouts();
PollPeriod period = new PollPeriod();
Function<TemplateOptions, Statement> templateOptionsToStatement = new TemplateOptionsToStatement();
Set<NodeMetadata> goodNodes = Sets.newLinkedHashSet();
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
@ -213,10 +215,10 @@ public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest {
GetNodeMetadataStrategy nodeClient = createMock(GetNodeMetadataStrategy.class);
AtomicNodeRunning nodeRunning = new AtomicNodeRunning(nodeClient);
Predicate<AtomicReference<NodeMetadata>> retryableNodeRunning = new ComputeServiceTimeoutsModule() {
public Predicate<AtomicReference<NodeMetadata>> nodeRunning(AtomicNodeRunning statusRunning, Timeouts timeouts) {
return super.nodeRunning(statusRunning, timeouts);
public Predicate<AtomicReference<NodeMetadata>> nodeRunning(AtomicNodeRunning statusRunning, Timeouts timeouts, PollPeriod period) {
return super.nodeRunning(statusRunning, timeouts, period);
}
}.nodeRunning(nodeRunning, timeouts);
}.nodeRunning(nodeRunning, timeouts, period);
AtomicReference<NodeMetadata> atomicNode = new AtomicReference<NodeMetadata>(pendingNode);
// Simulate transient error: first call returns null; subsequent calls return the running node

View File

@ -44,6 +44,9 @@ import com.google.common.base.Predicate;
* @author Adrian Cole
*/
public class RetryablePredicate<T> implements Predicate<T> {
public static final long DEFAULT_PERIOD = 50l;
public static final long DEFAULT_MAX_PERIOD = 1000l;
private final long maxWait;
private final long period;
private final long maxPeriod;
@ -63,8 +66,12 @@ public class RetryablePredicate<T> implements Predicate<T> {
this(predicate, maxWait, period, period * 10l, unit);
}
public RetryablePredicate(Predicate<T> predicate, long maxWait, long period, long maxPeriod) {
this(predicate, maxWait, period, maxPeriod, TimeUnit.MILLISECONDS);
}
public RetryablePredicate(Predicate<T> predicate, long maxWait) {
this(predicate, maxWait, 50l, 1000l, TimeUnit.MILLISECONDS);
this(predicate, maxWait, DEFAULT_PERIOD, DEFAULT_MAX_PERIOD, TimeUnit.MILLISECONDS);
}
@Override