Skip to content

Commit

Permalink
add namespace publish info tips
Browse files Browse the repository at this point in the history
  • Loading branch information
lepdou committed Dec 19, 2016
1 parent 7e4f6bc commit 3745164
Show file tree
Hide file tree
Showing 17 changed files with 420 additions and 87 deletions.
Expand Up @@ -17,6 +17,7 @@
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
public class NamespaceController {
Expand Down Expand Up @@ -89,4 +90,14 @@ public NamespaceDTO findPublicNamespace(@PathVariable String clusterName,

return BeanUtils.transfrom(NamespaceDTO.class, namespace);
}

/**
* cluster -> cluster has not published namespaces?
*/
@RequestMapping("/apps/{appId}/namespaces/publish_info")
public Map<String, Boolean> namespacePublishInfo(@PathVariable String appId){
return namespaceService.namespacePublishInfo(appId);
}


}
Expand Up @@ -6,6 +6,7 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;

import java.util.Date;
import java.util.List;

public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
Expand All @@ -14,6 +15,8 @@ public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {

List<Item> findByNamespaceIdOrderByLineNumAsc(Long namespaceId);

List<Item> findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(Long namespaceId, Date date);

Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId);

@Modifying
Expand Down
Expand Up @@ -12,13 +12,10 @@ public class AdminService {

@Autowired
private AppService appService;

@Autowired
private AppNamespaceService appNamespaceService;

@Autowired
private ClusterService clusterService;

@Autowired
private NamespaceService namespaceService;

Expand All @@ -38,4 +35,5 @@ public App createNewApp(App app) {
return app;
}


}
Expand Up @@ -23,6 +23,7 @@

import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
Expand Down Expand Up @@ -168,6 +169,10 @@ public List<Item> findItems(String appId, String clusterName, String namespaceNa
}
}

public List<Item> findItemsModifiedAfterDate(long namespaceId, Date date) {
return itemRepository.findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(namespaceId, date);
}

@Transactional
public Item save(Item entity) {
checkItemKeyLength(entity.getKey());
Expand Down
@@ -1,9 +1,15 @@
package com.ctrip.framework.apollo.biz.service;

import com.google.common.collect.Maps;
import com.google.gson.Gson;

import com.ctrip.framework.apollo.biz.entity.Audit;
import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
import com.ctrip.framework.apollo.common.constants.GsonType;
import com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import com.ctrip.framework.apollo.common.exception.BadRequestException;
Expand All @@ -17,14 +23,18 @@
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class NamespaceService {

private Gson gson = new Gson();

@Autowired
private NamespaceRepository namespaceRepository;
@Autowired
Expand Down Expand Up @@ -246,5 +256,59 @@ public void createPrivateNamespace(String appId, String clusterName, String crea

}

public Map<String, Boolean> namespacePublishInfo(String appId) {
List<Cluster> clusters = clusterService.findParentClusters(appId);
if (CollectionUtils.isEmpty(clusters)) {
throw new BadRequestException("app not exist");
}

Map<String, Boolean> clusterHasNotPublishedItems = Maps.newHashMap();

for (Cluster cluster : clusters) {
String clusterName = cluster.getName();
List<Namespace> namespaces = findNamespaces(appId, clusterName);

for (Namespace namespace: namespaces) {
boolean isNamespaceNotPublished = isNamespaceNotPublished(namespace);

if (isNamespaceNotPublished){
clusterHasNotPublishedItems.put(clusterName, true);
break;
}
}

clusterHasNotPublishedItems.putIfAbsent(clusterName, false);
}

return clusterHasNotPublishedItems;
}

private boolean isNamespaceNotPublished(Namespace namespace) {

Release latestRelease = releaseService.findLatestActiveRelease(namespace);
long namespaceId = namespace.getId();

if (latestRelease == null) {
Item lastItem = itemService.findLastOne(namespaceId);
return lastItem != null;
}

Date lastPublishTime = latestRelease.getDataChangeLastModifiedTime();
List<Item> itemsModifiedAfterLastPublish = itemService.findItemsModifiedAfterDate(namespaceId, lastPublishTime);

if (CollectionUtils.isEmpty(itemsModifiedAfterLastPublish)) {
return false;
}

Map<String, String> publishedConfiguration = gson.fromJson(latestRelease.getConfigurations(), GsonType.CONFIG);
for (Item item: itemsModifiedAfterLastPublish) {
if (!Objects.equals(item.getValue(), publishedConfiguration.get(item.getKey()))){
return true;
}
}

return false;
}


}
@@ -0,0 +1,134 @@
package com.ctrip.framework.apollo.biz.service;

import com.ctrip.framework.apollo.biz.AbstractUnitTest;
import com.ctrip.framework.apollo.biz.entity.Cluster;
import com.ctrip.framework.apollo.biz.entity.Item;
import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.repository.NamespaceRepository;
import com.ctrip.framework.apollo.core.ConfigConsts;

import org.junit.Assert;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.Collections;
import java.util.Map;
import java.util.Random;

import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.when;

public class NamespacePublishInfoTest extends AbstractUnitTest {

@Mock
private ClusterService clusterService;
@Mock
private ReleaseService releaseService;
@Mock
private ItemService itemService;
@Mock
private NamespaceRepository namespaceRepository;

@InjectMocks
private NamespaceService namespaceService;

private String testApp = "testApp";

@Test
public void testNamespaceNotEverPublishedButHasItems() {
Cluster cluster = createCluster(ConfigConsts.CLUSTER_NAME_DEFAULT);
Namespace namespace = createNamespace(ConfigConsts.CLUSTER_NAME_DEFAULT, ConfigConsts.NAMESPACE_APPLICATION);
Item item = createItem(namespace.getId(), "a", "b");

when(clusterService.findParentClusters(testApp)).thenReturn(Collections.singletonList(cluster));
when(namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(testApp, ConfigConsts.CLUSTER_NAME_DEFAULT))
.thenReturn(Collections.singletonList(namespace));
when(itemService.findLastOne(anyLong())).thenReturn(item);

Map<String, Boolean> result = namespaceService.namespacePublishInfo(testApp);

Assert.assertEquals(1, result.size());
Assert.assertTrue(result.get(ConfigConsts.CLUSTER_NAME_DEFAULT));
}

@Test
public void testNamespaceEverPublishedAndNotModifiedAfter() {
Cluster cluster = createCluster(ConfigConsts.CLUSTER_NAME_DEFAULT);
Namespace namespace = createNamespace(ConfigConsts.CLUSTER_NAME_DEFAULT, ConfigConsts.NAMESPACE_APPLICATION);
Item item = createItem(namespace.getId(), "a", "b");
Release release = createRelease("{\"a\":\"b\"}");

when(clusterService.findParentClusters(testApp)).thenReturn(Collections.singletonList(cluster));
when(namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(testApp, ConfigConsts.CLUSTER_NAME_DEFAULT))
.thenReturn(Collections.singletonList(namespace));
when(releaseService.findLatestActiveRelease(namespace)).thenReturn(release);
when(itemService.findItemsModifiedAfterDate(anyLong(), anyObject())).thenReturn(Collections.singletonList(item));

Map<String, Boolean> result = namespaceService.namespacePublishInfo(testApp);

Assert.assertEquals(1, result.size());
Assert.assertFalse(result.get(ConfigConsts.CLUSTER_NAME_DEFAULT));

}

@Test
public void testNamespaceEverPublishedAndModifiedAfter() {
Cluster cluster = createCluster(ConfigConsts.CLUSTER_NAME_DEFAULT);
Namespace namespace = createNamespace(ConfigConsts.CLUSTER_NAME_DEFAULT, ConfigConsts.NAMESPACE_APPLICATION);
Item item = createItem(namespace.getId(), "a", "b");
Release release = createRelease("{\"a\":\"c\"}");

when(clusterService.findParentClusters(testApp)).thenReturn(Collections.singletonList(cluster));
when(namespaceRepository.findByAppIdAndClusterNameOrderByIdAsc(testApp, ConfigConsts.CLUSTER_NAME_DEFAULT))
.thenReturn(Collections.singletonList(namespace));
when(releaseService.findLatestActiveRelease(namespace)).thenReturn(release);
when(itemService.findItemsModifiedAfterDate(anyLong(), anyObject())).thenReturn(Collections.singletonList(item));

Map<String, Boolean> result = namespaceService.namespacePublishInfo(testApp);

Assert.assertEquals(1, result.size());
Assert.assertTrue(result.get(ConfigConsts.CLUSTER_NAME_DEFAULT));

}

private Cluster createCluster(String clusterName) {
Cluster cluster = new Cluster();

cluster.setAppId(testApp);
cluster.setName(clusterName);
cluster.setParentClusterId(0);

return cluster;
}

private Namespace createNamespace(String clusterName, String namespaceName) {
Namespace namespace = new Namespace();

namespace.setAppId(testApp);
namespace.setClusterName(clusterName);
namespace.setNamespaceName(namespaceName);
namespace.setId(new Random().nextLong());

return namespace;
}

private Item createItem(long namespaceId, String key, String value) {
Item item = new Item();

item.setNamespaceId(namespaceId);
item.setKey(key);
item.setValue(value);

return item;
}

private Release createRelease(String configuration) {
Release release = new Release();
release.setConfigurations(configuration);
return release;
}

}
Expand Up @@ -32,6 +32,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;


Expand Down Expand Up @@ -62,6 +63,10 @@ public AppDTO createApp(Env env, AppDTO app) {
@Service
public static class NamespaceAPI extends API {

private ParameterizedTypeReference<Map<String, Boolean>>
typeReference = new ParameterizedTypeReference<Map<String, Boolean>>() {
};

public List<NamespaceDTO> findNamespaceByCluster(String appId, Env env, String clusterName) {
NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces",
NamespaceDTO[].class, appId,
Expand Down Expand Up @@ -100,6 +105,10 @@ public void deleteNamespace(Env env, String appId, String clusterName, String na
namespaceName, operator);
}

public Map<String, Boolean> getNamespacePublishInfo(Env env, String appId) {
return restTemplate.get(env, "apps/{appId}/namespaces/publish_info", typeReference, appId).getBody();
}

}

@Service
Expand Down
Expand Up @@ -35,10 +35,10 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

import static com.ctrip.framework.apollo.common.utils.RequestPrecondition.checkModel;

Expand Down Expand Up @@ -169,4 +169,18 @@ public AppNamespace createAppNamespace(@PathVariable String appId, @RequestBody
return createdAppNamespace;
}


/**
* env -> cluster -> cluster has not published namespace?
* Example:
* dev ->
* default -> true (default cluster has not published namespace)
* customCluster -> false (customCluster cluster's all namespaces had published)
*
*/
@RequestMapping("/apps/{appId}/namespaces/publish_info")
public Map<String, Map<String, Boolean>> getNamespacesPublishInfo(@PathVariable String appId) {
return namespaceService.getNamespacesPublishInfo(appId);
}

}

0 comments on commit 3745164

Please sign in to comment.