package com.netflix.schlep.sqs; import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.services.sqs.AmazonSQSClient; import com.amazonaws.services.sqs.model.CreateQueueRequest; import com.amazonaws.services.sqs.model.DeleteQueueRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesResult; import com.amazonaws.services.sqs.model.ListQueuesResult; import com.amazonaws.services.sqs.model.SetQueueAttributesRequest; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import com.google.inject.Inject; import com.google.inject.Provider; import com.netflix.schlep.admin.QueueAdmin; import com.netflix.schlep.admin.QueueAttributes; public class SqsQueueAdmin implements QueueAdmin { private final int DEFAULT_MAX_RETRIES = 3; private final int DEFAULT_TIMEOUT = 5000; private final String DEFAULT_REGION = "us-east"; private final AmazonSQSClient client; @Inject public SqsQueueAdmin(Provider<AWSCredentials> awsCredentials) { // Construct the client this.client = new AmazonSQSClient(awsCredentials.get(), new ClientConfiguration() .withConnectionTimeout(DEFAULT_TIMEOUT) .withSocketTimeout (DEFAULT_TIMEOUT) .withMaxConnections (DEFAULT_TIMEOUT) .withMaxErrorRetry (DEFAULT_MAX_RETRIES) ); // Modify the region endpoint client.setEndpoint(DEFAULT_REGION); } @Override public ListenableFuture<Boolean> createQueue(final String uri,final QueueAttributes attributes) { return submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { CreateQueueRequest createRequest = new CreateQueueRequest() .withQueueName(uri) .withAttributes(attributes.getAttributes()); client.createQueue(createRequest); return true; } }); } @Override public ListenableFuture<Boolean> deleteQueue(final String uri) { return submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { DeleteQueueRequest request = new DeleteQueueRequest() .withQueueUrl(uri); client.deleteQueue(request); return true; } }); } @Override public ListenableFuture<QueueAttributes> getQueueAttributes(final String uri, final Collection<String> attributes) { return submit(new Callable<QueueAttributes>() { @Override public QueueAttributes call() throws Exception { GetQueueAttributesResult result = client.getQueueAttributes(new GetQueueAttributesRequest() .withQueueUrl(uri) .withAttributeNames(attributes)); return new QueueAttributes().withAttributes(result.getAttributes()); } }); } @Override public ListenableFuture<Void> updateQueueAttributes(final String uri, final QueueAttributes attributes) { return submit(new Callable<Void>() { @Override public Void call() throws Exception { // TODO: Validate attribute list or filter out unsupported attributes client.setQueueAttributes(new SetQueueAttributesRequest() .withQueueUrl(uri) .withAttributes(attributes.getAttributes())); return null; } }); } @Override public ListenableFuture<List<String>> listQueues() { return submit(new Callable<List<String>>() { @Override public List<String> call() throws Exception { ListQueuesResult result = client.listQueues(); return result.getQueueUrls(); } }); } @Override public ListenableFuture<QueueAttributes> getQueueAttributes(String queueName) { return getQueueAttributes(queueName, null); } @Override public ListenableFuture<Long> getQueueMessageCount(final String uri) { return submit(new Callable<Long>() { @Override public Long call() throws Exception { GetQueueAttributesResult result = client.getQueueAttributes(new GetQueueAttributesRequest() .withQueueUrl(uri) .withAttributeNames(SqsQueueAttribute.ApproximateNumberOfMessages.name())); try { return Long.valueOf(result.getAttributes().get(SqsQueueAttribute.ApproximateNumberOfMessages.name())); } catch (Exception e) { throw new RuntimeException("Failed to get queue depth for queue: " + uri, e); } } }); } private <V> ListenableFuture<V> submit(Callable<V> callable) { SettableFuture<V> future = SettableFuture.create(); try { future.set(callable.call()); } catch (Exception e) { future.setException(e); } return future; } }