Skip to content
Permalink
Browse files
JCLOUDS-457: Add polling strategy
The polling strategy interface for job operations
and a simple implementation class have been added.
This implementation waits an initial time and then
polls at regular intervals.
  • Loading branch information
rcoedo authored and gaul committed Jul 26, 2014
1 parent 36e8cbd commit 3bc840e6794fa7cc5a62c5bc4632911ed44d45b0
Showing 5 changed files with 110 additions and 9 deletions.
@@ -37,6 +37,7 @@
import org.jclouds.glacier.GlacierClient;
import org.jclouds.glacier.blobstore.functions.PaginatedVaultCollectionToStorageMetadata;
import org.jclouds.glacier.blobstore.strategy.MultipartUploadStrategy;
import org.jclouds.glacier.blobstore.strategy.PollingStrategy;
import org.jclouds.javax.annotation.Nullable;

import com.google.common.base.Supplier;
@@ -47,13 +48,17 @@ public class GlacierBlobStore extends BaseBlobStore {
private final GlacierClient sync;
private final Crypto crypto;
private final Provider<MultipartUploadStrategy> multipartUploadStrategy;
private final Provider<PollingStrategy> pollingStrategy;
private final PaginatedVaultCollectionToStorageMetadata vaultsToContainers;

@Inject
GlacierBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations, GlacierClient sync, Crypto crypto,
Provider<MultipartUploadStrategy> multipartUploadStrategy, PaginatedVaultCollectionToStorageMetadata vaultsToContainers) {
Provider<MultipartUploadStrategy> multipartUploadStrategy,
Provider<PollingStrategy> pollingStrategy,
PaginatedVaultCollectionToStorageMetadata vaultsToContainers) {
super(context, blobUtils, defaultLocation, locations);
this.pollingStrategy = checkNotNull(pollingStrategy, "pollingStrategy");
this.vaultsToContainers = checkNotNull(vaultsToContainers, "vaultsToContainers");
this.multipartUploadStrategy = checkNotNull(multipartUploadStrategy, "multipartUploadStrategy");
this.sync = checkNotNull(sync, "sync");
@@ -24,7 +24,9 @@
import org.jclouds.glacier.blobstore.GlacierBlobStore;
import org.jclouds.glacier.blobstore.strategy.ClearVaultStrategy;
import org.jclouds.glacier.blobstore.strategy.MultipartUploadStrategy;
import org.jclouds.glacier.blobstore.strategy.PollingStrategy;
import org.jclouds.glacier.blobstore.strategy.SlicingStrategy;
import org.jclouds.glacier.blobstore.strategy.internal.BasePollingStrategy;
import org.jclouds.glacier.blobstore.strategy.internal.BaseSlicingStrategy;
import org.jclouds.glacier.blobstore.strategy.internal.SequentialMultipartUploadStrategy;

@@ -39,5 +41,6 @@ protected void configure() {
bind(MultipartUploadStrategy.class).to(SequentialMultipartUploadStrategy.class);
bind(SlicingStrategy.class).to(BaseSlicingStrategy.class);
bind(ClearListStrategy.class).to(ClearVaultStrategy.class);
bind(PollingStrategy.class).to(BasePollingStrategy.class);
}
}
@@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.glacier.blobstore.strategy;

public interface PollingStrategy {
boolean waitForSuccess(String vault, String job) throws InterruptedException;
}
@@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.glacier.blobstore.strategy.internal;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.concurrent.TimeUnit;

import org.jclouds.glacier.GlacierClient;
import org.jclouds.glacier.blobstore.strategy.PollingStrategy;
import org.jclouds.glacier.domain.JobMetadata;
import org.jclouds.glacier.domain.JobStatus;

import com.google.inject.Inject;

public class BasePollingStrategy implements PollingStrategy {
public static final long DEFAULT_INITIAL_WAIT = TimeUnit.HOURS.toMillis(3);
public static final long DEFAULT_TIME_BETWEEN_POLLS = TimeUnit.MINUTES.toMillis(15);

private final GlacierClient client;
private final long initialWait;
private final long timeBetweenPolls;

public BasePollingStrategy(long initialWait, long timeBetweenPolls, GlacierClient client) {
this.initialWait = initialWait;
this.timeBetweenPolls = timeBetweenPolls;
this.client = checkNotNull(client, "client");
}

@Inject
public BasePollingStrategy(GlacierClient client) {
this(DEFAULT_INITIAL_WAIT, DEFAULT_TIME_BETWEEN_POLLS, client);
}

private boolean inProgress(String job, String vault) {
JobMetadata jobMetadata = client.describeJob(vault, job);
return (jobMetadata != null) && (jobMetadata.getStatusCode() == JobStatus.IN_PROGRESS);
}

private void waitForJob(String job, String vault) throws InterruptedException {
Thread.sleep(initialWait);
while (inProgress(job, vault)) {
Thread.sleep(timeBetweenPolls);
}
}

private boolean succeeded(String job, String vault) {
JobMetadata jobMetadata = client.describeJob(vault, job);
return (jobMetadata != null) && (jobMetadata.getStatusCode() == JobStatus.SUCCEEDED);
}

@Override
public boolean waitForSuccess(String vault, String job) throws InterruptedException {
// Avoid waiting if the job doesn't exist
if (client.describeJob(vault, job) == null) {
return false;
}
waitForJob(job, vault);
return succeeded(job, vault);
}

}
@@ -17,15 +17,16 @@
package org.jclouds.glacier;

import static org.assertj.core.api.Assertions.assertThat;
import static org.jclouds.glacier.blobstore.strategy.internal.BasePollingStrategy.DEFAULT_TIME_BETWEEN_POLLS;
import static org.jclouds.glacier.util.TestUtils.MiB;
import static org.jclouds.glacier.util.TestUtils.buildData;
import static org.jclouds.glacier.util.TestUtils.buildPayload;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.glacier.blobstore.strategy.internal.BasePollingStrategy;
import org.jclouds.glacier.domain.ArchiveRetrievalJobRequest;
import org.jclouds.glacier.domain.InventoryRetrievalJobRequest;
import org.jclouds.glacier.domain.JobMetadata;
@@ -44,8 +45,6 @@
public class GlacierClientLongLiveTest extends BaseApiLiveTest<GlacierClient>{

private static final long PART_SIZE = 1;
private static final long INITIAL_WAIT = TimeUnit.HOURS.toMillis(3);
private static final long TIME_BETWEEN_POLLS = TimeUnit.MINUTES.toMillis(15);
private static final String VAULT_NAME = "JCLOUDS_LIVE_TESTS";
private static final String ARCHIVE_DESCRIPTION = "test archive";

@@ -112,11 +111,8 @@ public void testListJobs() {

@Test(groups = {"live", "livelong", "longtest"}, dependsOnMethods = {"testInitiateJob", "testDescribeJob", "testListJobs"})
public void testWaitForSucceed() throws InterruptedException {
Thread.sleep(INITIAL_WAIT);
while (api.describeJob(VAULT_NAME, archiveRetrievalJob).getStatusCode() == JobStatus.IN_PROGRESS ||
api.describeJob(VAULT_NAME, inventoryRetrievalJob).getStatusCode() == JobStatus.IN_PROGRESS) {
Thread.sleep(TIME_BETWEEN_POLLS);
}
new BasePollingStrategy(api).waitForSuccess(VAULT_NAME, archiveRetrievalJob);
new BasePollingStrategy(0, DEFAULT_TIME_BETWEEN_POLLS, api).waitForSuccess(VAULT_NAME, inventoryRetrievalJob);
assertThat(api.describeJob(VAULT_NAME, archiveRetrievalJob).getStatusCode()).isEqualTo(JobStatus.SUCCEEDED);
assertThat(api.describeJob(VAULT_NAME, inventoryRetrievalJob).getStatusCode()).isEqualTo(JobStatus.SUCCEEDED);
}

0 comments on commit 3bc840e

Please sign in to comment.