Commit 6dfefd8d by Jason Song Committed by GitHub

Merge pull request #466 from nobodyiam/support-large-file

support large file with namespace value length limit override
parents fc4f3e85 0a6267d6
package com.ctrip.framework.apollo.biz.service;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.biz.entity.Namespace;
......@@ -7,17 +11,30 @@ import com.ctrip.framework.apollo.biz.repository.ItemRepository;
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.exception.NotFoundException;
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@Service
public class ItemService {
public class ItemService implements InitializingBean {
private static final int DEFAULT_LIMIT_UPDATE_INTERVAL_IN_SECONDS = 60;
@Autowired
private ItemRepository itemRepository;
......@@ -31,6 +48,61 @@ public class ItemService {
@Autowired
private ServerConfigService serverConfigService;
private AtomicInteger globalKeyLengthLimit;
private AtomicInteger globalValueLengthLimit;
private AtomicReference<Map<Long, Integer>> namespaceValueLengthOverride;
private Gson gson;
private ScheduledExecutorService executorService;
private static final Type namespaceValueLengthOverrideTypeReference =
new TypeToken<Map<Long, Integer>>() {
}.getType();
public ItemService() {
gson = new Gson();
globalKeyLengthLimit = new AtomicInteger(128);
globalValueLengthLimit = new AtomicInteger(20000);
namespaceValueLengthOverride = new AtomicReference<>();
executorService = Executors.newScheduledThreadPool(1, ApolloThreadFactory
.create("ItemServiceLimitUpdater", true));
}
@Override
public void afterPropertiesSet() throws Exception {
executorService.scheduleWithFixedDelay(() -> {
Transaction transaction = Cat.newTransaction("Apollo.ItemServiceLimitUpdater", "updateLimit");
try {
updateLimits();
transaction.setStatus(Message.SUCCESS);
} catch (Throwable ex) {
transaction.setStatus(ex);
} finally {
transaction.complete();
}
}, 0, getLimitUpdateIntervalInSeconds(), TimeUnit.SECONDS);
}
private void updateLimits() {
String keyLengthLimit = serverConfigService.getValue("item.key.length.limit", null);
if (!Strings.isNullOrEmpty(keyLengthLimit)) {
globalKeyLengthLimit.set(Integer.valueOf(keyLengthLimit));
}
String valueLengthLimit = serverConfigService.getValue("item.value.length.limit", null);
if (!Strings.isNullOrEmpty(valueLengthLimit)) {
globalValueLengthLimit.set(Integer.valueOf(valueLengthLimit));
}
String namespaceValueLengthOverrideString =
serverConfigService.getValue("namespace.value.length.limit.override", null);
if (!Strings.isNullOrEmpty(namespaceValueLengthOverrideString)) {
namespaceValueLengthOverride.set(gson.fromJson(
namespaceValueLengthOverrideString, namespaceValueLengthOverrideTypeReference));
}
}
@Transactional
public Item delete(long id, String operator) {
Item item = itemRepository.findOne(id);
......@@ -100,7 +172,7 @@ public class ItemService {
@Transactional
public Item save(Item entity) {
checkItemKeyLength(entity.getKey());
checkItemValueLength(entity.getValue());
checkItemValueLength(entity.getNamespaceId(), entity.getValue());
entity.setId(0);//protection
......@@ -120,7 +192,7 @@ public class ItemService {
@Transactional
public Item update(Item item) {
checkItemValueLength(item.getValue());
checkItemValueLength(item.getNamespaceId(), item.getValue());
Item managedItem = itemRepository.findOne(item.getId());
BeanUtils.copyEntityProperties(item, managedItem);
managedItem = itemRepository.save(managedItem);
......@@ -131,20 +203,30 @@ public class ItemService {
return managedItem;
}
private boolean checkItemValueLength(String value) {
int lengthLimit = Integer.valueOf(serverConfigService.getValue("item.value.length.limit", "20000"));
if (!StringUtils.isEmpty(value) && value.length() > lengthLimit) {
throw new BadRequestException("value too long. length limit:" + lengthLimit);
private boolean checkItemValueLength(long namespaceId, String value) {
int limit = getItemValueLengthLimit(namespaceId);
if (!StringUtils.isEmpty(value) && value.length() > limit) {
throw new BadRequestException("value too long. length limit:" + limit);
}
return true;
}
private boolean checkItemKeyLength(String key) {
int lengthLimit = Integer.valueOf(serverConfigService.getValue("item.key.length.limit", "128"));
if (!StringUtils.isEmpty(key) && key.length() > lengthLimit) {
throw new BadRequestException("key too long. length limit:" + lengthLimit);
if (!StringUtils.isEmpty(key) && key.length() > globalKeyLengthLimit.get()) {
throw new BadRequestException("key too long. length limit:" + globalKeyLengthLimit.get());
}
return true;
}
private int getItemValueLengthLimit(long namespaceId) {
if (namespaceValueLengthOverride.get() != null && namespaceValueLengthOverride.get()
.containsKey(namespaceId)) {
return namespaceValueLengthOverride.get().get(namespaceId);
}
return globalValueLengthLimit.get();
}
private int getLimitUpdateIntervalInSeconds() {
return DEFAULT_LIMIT_UPDATE_INTERVAL_IN_SECONDS;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment