package com.ctrip.framework.apollo.biz.service;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.ctrip.framework.apollo.biz.entity.Instance;
import com.ctrip.framework.apollo.biz.entity.InstanceConfig;
import com.ctrip.framework.apollo.biz.repository.InstanceConfigRepository;
import com.ctrip.framework.apollo.biz.repository.InstanceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Service
public class InstanceService {
@Autowired
private InstanceRepository instanceRepository;
@Autowired
private InstanceConfigRepository instanceConfigRepository;
public Instance findInstance(String appId, String clusterName, String dataCenter, String ip) {
return instanceRepository.findByAppIdAndClusterNameAndDataCenterAndIp(appId, clusterName,
dataCenter, ip);
}
public List<Instance> findInstancesByIds(Set<Long> instanceIds) {
Iterable<Instance> instances = instanceRepository.findAll(instanceIds);
if (instances == null) {
return Collections.emptyList();
}
return Lists.newArrayList(instances);
}
@Transactional
public Instance createInstance(Instance instance) {
instance.setId(0); //protection
return instanceRepository.save(instance);
}
public InstanceConfig findInstanceConfig(long instanceId, String configAppId, String
configNamespaceName) {
return instanceConfigRepository
.findByInstanceIdAndConfigAppIdAndConfigNamespaceName(
instanceId, configAppId, configNamespaceName);
}
public Page<InstanceConfig> findActiveInstanceConfigsByReleaseKey(String releaseKey, Pageable
pageable) {
Page<InstanceConfig> instanceConfigs = instanceConfigRepository
.findByReleaseKeyAndDataChangeLastModifiedTimeAfter(releaseKey,
getValidInstanceConfigDate(), pageable);
return instanceConfigs;
}
public Page<Instance> findInstancesByNamespace(String appId, String clusterName, String
namespaceName, Pageable pageable) {
Page<InstanceConfig> instanceConfigs = instanceConfigRepository.
findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfter(appId, clusterName,
namespaceName, getValidInstanceConfigDate(), pageable);
List<Instance> instances = Collections.emptyList();
if (instanceConfigs.hasContent()) {
Set<Long> instanceIds = instanceConfigs.getContent().stream().map
(InstanceConfig::getInstanceId).collect(Collectors.toSet());
instances = findInstancesByIds(instanceIds);
}
return new PageImpl<>(instances, pageable, instanceConfigs.getTotalElements());
}
public Page<Instance> findInstancesByNamespaceAndInstanceAppId(String instanceAppId, String
appId, String clusterName, String
namespaceName, Pageable
pageable) {
Page<Object[]> instanceIdResult = instanceConfigRepository
.findInstanceIdsByNamespaceAndInstanceAppId(instanceAppId, appId, clusterName,
namespaceName, getValidInstanceConfigDate(), pageable);
List<Instance> instances = Collections.emptyList();
if (instanceIdResult.hasContent()) {
Set<Long> instanceIds = instanceIdResult.getContent().stream().map((Object o) -> {
if (o == null) {
return null;
}
if (o instanceof Integer) {
return ((Integer)o).longValue();
}
if (o instanceof Long) {
return (Long) o;
}
//for h2 test
if (o instanceof BigInteger) {
return ((BigInteger) o).longValue();
}
return null;
}).filter((Long value) -> value != null).collect(Collectors.toSet());
instances = findInstancesByIds(instanceIds);
}
return new PageImpl<>(instances, pageable, instanceIdResult.getTotalElements());
}
public List<InstanceConfig> findInstanceConfigsByNamespaceWithReleaseKeysNotIn(String appId,
String clusterName,
String
namespaceName,
Set<String>
releaseKeysNotIn) {
List<InstanceConfig> instanceConfigs = instanceConfigRepository.
findByConfigAppIdAndConfigClusterNameAndConfigNamespaceNameAndDataChangeLastModifiedTimeAfterAndReleaseKeyNotIn(appId, clusterName,
namespaceName, getValidInstanceConfigDate(), releaseKeysNotIn);
if (CollectionUtils.isEmpty(instanceConfigs)) {
return Collections.emptyList();
}
return instanceConfigs;
}
/**
* Currently the instance config is expired by 1 day, add one more hour to avoid possible time
* difference
*/
private Date getValidInstanceConfigDate() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
cal.add(Calendar.HOUR, -1);
return cal.getTime();
}
@Transactional
public InstanceConfig createInstanceConfig(InstanceConfig instanceConfig) {
instanceConfig.setId(0); //protection
return instanceConfigRepository.save(instanceConfig);
}
@Transactional
public InstanceConfig updateInstanceConfig(InstanceConfig instanceConfig) {
InstanceConfig existedInstanceConfig = instanceConfigRepository.findOne(instanceConfig.getId());
Preconditions.checkArgument(existedInstanceConfig != null, String.format(
"Instance config %d doesn't exist", instanceConfig.getId()));
existedInstanceConfig.setConfigClusterName(instanceConfig.getConfigClusterName());
existedInstanceConfig.setReleaseKey(instanceConfig.getReleaseKey());
existedInstanceConfig.setReleaseDeliveryTime(instanceConfig.getReleaseDeliveryTime());
existedInstanceConfig.setDataChangeLastModifiedTime(instanceConfig
.getDataChangeLastModifiedTime());
return instanceConfigRepository.save(existedInstanceConfig);
}
@Transactional
public int batchDeleteInstanceConfig(String configAppId, String configClusterName, String configNamespaceName){
return instanceConfigRepository.batchDelete(configAppId, configClusterName, configNamespaceName);
}
}