/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed 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.springframework.cloud.aws.cache;
import com.amazonaws.services.elasticache.AmazonElastiCache;
import com.amazonaws.services.elasticache.model.CacheCluster;
import com.amazonaws.services.elasticache.model.DescribeCacheClustersRequest;
import com.amazonaws.services.elasticache.model.DescribeCacheClustersResult;
import com.amazonaws.services.elasticache.model.Endpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.cache.Cache;
import org.springframework.cloud.aws.core.env.ResourceIdResolver;
import java.util.List;
/**
* @author Agim Emruli
*/
public class ElastiCacheFactoryBean extends AbstractFactoryBean<Cache> {
private static final Logger LOGGER = LoggerFactory.getLogger(ElastiCacheFactoryBean.class);
private final AmazonElastiCache amazonElastiCache;
private final String cacheClusterId;
private final ResourceIdResolver resourceIdResolver;
private final List<? extends CacheFactory> cacheFactories;
public ElastiCacheFactoryBean(AmazonElastiCache amazonElastiCache, String cacheClusterId,
ResourceIdResolver resourceIdResolver, List<? extends CacheFactory> cacheFactories) {
this.amazonElastiCache = amazonElastiCache;
this.resourceIdResolver = resourceIdResolver;
this.cacheClusterId = cacheClusterId;
this.cacheFactories = cacheFactories;
}
public ElastiCacheFactoryBean(AmazonElastiCache amazonElastiCache, String cacheClusterId, List<CacheFactory> cacheFactories) {
this(amazonElastiCache, cacheClusterId, null, cacheFactories);
}
@Override
public Class<Cache> getObjectType() {
return Cache.class;
}
@Override
protected Cache createInstance() throws Exception {
DescribeCacheClustersRequest describeCacheClustersRequest = new DescribeCacheClustersRequest().withCacheClusterId(getCacheClusterName());
describeCacheClustersRequest.setShowCacheNodeInfo(true);
DescribeCacheClustersResult describeCacheClustersResult = this.amazonElastiCache.describeCacheClusters(describeCacheClustersRequest);
CacheCluster cacheCluster = describeCacheClustersResult.getCacheClusters().get(0);
if (!"available".equals(cacheCluster.getCacheClusterStatus())) {
LOGGER.warn("Cache cluster is not available now. Connection may fail during cache access. Current status is {}", cacheCluster.getCacheClusterStatus());
}
Endpoint configurationEndpoint = getEndpointForCache(cacheCluster);
for (CacheFactory cacheFactory : this.cacheFactories) {
if (cacheFactory.isSupportingCacheArchitecture(cacheCluster.getEngine())) {
return cacheFactory.createCache(this.cacheClusterId, configurationEndpoint.getAddress(), configurationEndpoint.getPort());
}
}
throw new IllegalArgumentException("No CacheFactory configured for engine: " + cacheCluster.getEngine());
}
@Override
protected void destroyInstance(Cache instance) throws Exception {
if (instance instanceof DisposableBean) {
((DisposableBean) instance).destroy();
}
}
private String getCacheClusterName() {
return this.resourceIdResolver != null ? this.resourceIdResolver.resolveToPhysicalResourceId(this.cacheClusterId) : this.cacheClusterId;
}
private static Endpoint getEndpointForCache(CacheCluster cacheCluster) {
if (cacheCluster.getConfigurationEndpoint() != null) {
return cacheCluster.getConfigurationEndpoint();
}
if (!cacheCluster.getCacheNodes().isEmpty()) {
return cacheCluster.getCacheNodes().get(0).getEndpoint();
}
throw new IllegalArgumentException("No Configuration Endpoint or Cache Node available to " +
"receive address information for cluster:'" + cacheCluster.getCacheClusterId() + "'");
}
}