com.symphony.oss.fugue.aws.sqs.SqsQueueManager Maven / Gradle / Ivy
/*
*
*
* Copyright 2018 Symphony Communication Services, LLC.
*
* Licensed to The Symphony Software Foundation (SSF) 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 com.symphony.oss.fugue.aws.sqs;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.QueueDoesNotExistException;
import com.amazonaws.services.sqs.model.TagQueueRequest;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.symphony.oss.commons.fault.CodingFault;
import com.symphony.oss.commons.fault.FaultAccumulator;
import com.symphony.oss.commons.fluent.BaseAbstractBuilder;
import com.symphony.oss.fugue.pubsub.IQueueManager;
import com.symphony.oss.fugue.pubsub.IQueueReceiver;
import com.symphony.oss.fugue.pubsub.IQueueSender;
import com.symphony.oss.fugue.pubsub.QueueNotFoundException;
/**
* AWS SQS implementation of QueueManager.
*
*
* @author Bruce Skingle
*
*/
public class SqsQueueManager implements IQueueManager
{
protected static final int MAX_MESSAGE_SIZE = 256 * 1024; // 256K
private static final Logger log_ = LoggerFactory.getLogger(SqsQueueManager.class);
private final String region_;
private final String accountId_;
private final ImmutableMap tags_;
private final AmazonSQS sqsClient_;
//private Map senderMap_ = new HashMap<>();
private final LoadingCache senderCache_ = CacheBuilder.newBuilder()
.maximumSize(250)
.build(
new CacheLoader()
{
@Override
public SqsQueueSender load(String queueName)
{
return new SqsQueueSender(sqsClient_, queueName);
}
});
private final LoadingCache receiverCache_ = CacheBuilder.newBuilder()
.maximumSize(250)
.build(
new CacheLoader()
{
@Override
public SqsQueueReceiver load(String queueName)
{
return new SqsQueueReceiver(sqsClient_, queueName);
}
});
private SqsQueueManager(Builder builder)
{
region_ = builder.region_;
accountId_ = builder.accountId_;
tags_ = ImmutableMap.copyOf(builder.tags_);
sqsClient_ = builder.sqsBuilder_.withRegion(region_).build();
}
@Override
public IQueueSender getSender(String queueName)
{
try
{
return senderCache_.get(queueName);
}
catch (ExecutionException e)
{
throw new CodingFault("Can't Happen", e);
}
}
@Override
public IQueueReceiver getReceiver(String queueName) throws QueueNotFoundException
{
try
{
return receiverCache_.get(queueName);
}
catch (ExecutionException e)
{
throw new CodingFault("Can't Happen", e);
}
catch(UncheckedExecutionException e)
{
if(e.getCause() instanceof QueueDoesNotExistException)
throw new QueueNotFoundException("Queue does not exist", e);
if(e.getCause() instanceof RuntimeException)
throw (RuntimeException)e.getCause();
throw e;
}
}
@Override
public int getMaximumMessageSize()
{
return MAX_MESSAGE_SIZE;
}
private String getQueueARN(String queueName)
{
return "arn:aws:sqs:" + region_ + ":" + accountId_ + ":" + queueName;
}
/**
* Concrete builder.
*
* @author Bruce Skingle
*
*/
public static class Builder extends BaseAbstractBuilder
{
private AmazonSQSClientBuilder sqsBuilder_;
private String region_;
private String accountId_;
private Map tags_ = new HashMap<>();
// private String configPath_ = "org/symphonyoss/s2/fugue/aws/sqs";
/**
* Constructor.
*/
public Builder()
{
super(Builder.class);
sqsBuilder_ = AmazonSQSClientBuilder
.standard()
.withClientConfiguration(new ClientConfiguration()
.withMaxConnections(200)
);
}
// @Override
// protected String getConfigPath()
// {
// return configPath_;
// }
//
// /**
// * Set the AWS region.
// *
// * @param configPath The path in the global configuration from which to take config.
// *
// * @return this (fluent method)
// */
// public Builder withConfigPath(String configPath)
// {
// configPath_ = configPath;
//
// return self();
// }
/**
* Set the AWS region.
*
* @param region The AWS region in which to operate.
*
* @return this (fluent method)
*/
public Builder withRegion(String region)
{
region_ = region;
sqsBuilder_.withRegion(region_);
return self();
}
/**
* Set the AWS account ID.
*
* @param accountId The ID of the AWS account in which to operate.
*
* @return this (fluent method)
*/
public Builder withAccountId(String accountId)
{
accountId_ = accountId;
return self();
}
/**
* Set the AWS credentials provider.
*
* @param credentialsProvider An AWS credentials provider.
*
* @return this (fluent method)
*/
public Builder withCredentials(AWSCredentialsProvider credentialsProvider)
{
sqsBuilder_.withCredentials(credentialsProvider);
return self();
}
/**
* Add the given tags to created queues.
* Multiple calls to this method are cumulative.
*
* @param tags Tags to add.
*
* @return this (fluent method)
*/
public Builder withTags(Map tags)
{
tags_.putAll(tags);
return self();
}
@Override
public void validate(FaultAccumulator faultAccumulator)
{
super.validate(faultAccumulator);
faultAccumulator.checkNotNull(region_, "region");
faultAccumulator.checkNotNull(accountId_, "accountId");
}
@Override
protected SqsQueueManager construct()
{
return new SqsQueueManager(this);
}
}
@Override
public boolean doesQueueExist(String queueName)
{
try
{
sqsClient_.getQueueUrl(queueName.toString()).getQueueUrl();
return true;
}
catch(QueueDoesNotExistException e)
{
return false;
}
}
@Override
public String createQueue(String queueName, Map tags, boolean dryRun)
{
String queueUrl;
try
{
queueUrl = sqsClient_.getQueueUrl(queueName.toString()).getQueueUrl();
log_.info("Queue " + queueName + " already exists as " + queueUrl);
}
catch(QueueDoesNotExistException e)
{
if(dryRun)
{
log_.info("Queue " + queueName + " would be created (dry run)");
return getQueueARN(queueName);
}
else
{
queueUrl = sqsClient_.createQueue(new CreateQueueRequest(queueName.toString())).getQueueUrl();
log_.info("Created queue " + queueName + " as " + queueUrl);
}
}
Map effectiveTags;
if(tags == null || tags.isEmpty())
{
effectiveTags = tags_;
}
else
{
effectiveTags = new HashMap<>(tags_);
effectiveTags.putAll(tags);
}
sqsClient_.tagQueue(new TagQueueRequest()
.withQueueUrl(queueUrl)
.withTags(effectiveTags)
);
return getQueueARN(queueName);
}
@Override
public void deleteQueue(String queueName, boolean dryRun)
{
try
{
String existingQueueUrl = sqsClient_.getQueueUrl(queueName.toString()).getQueueUrl();
if(dryRun)
{
log_.info("Subscription " + queueName + " with URL " + existingQueueUrl + " would be deleted (dry run)");
}
else
{
sqsClient_.deleteQueue(existingQueueUrl);
log_.info("Deleted queue " + queueName + " with URL " + existingQueueUrl);
}
}
catch(QueueDoesNotExistException e)
{
log_.info("Queue " + queueName + " does not exist.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy