public List<NamespaceBO> findNamespaceBOs(String appId, Env env, String clusterName, boolean includeDeletedItems) {

    List<NamespaceDTO> namespaces = namespaceAPI.findNamespaceByCluster(appId, env, clusterName);
    if (namespaces == null || namespaces.size() == 0) {
      throw BadRequestException.namespaceNotExists();
    }

    List<NamespaceBO> namespaceBOs = Collections.synchronizedList(new LinkedList<>());
    List<String> exceptionNamespaces = Collections.synchronizedList(new LinkedList<>());
    CountDownLatch latch = new CountDownLatch(namespaces.size());
    for (NamespaceDTO namespace : namespaces) {
      executorService.submit(() -> {
        NamespaceBO namespaceBO;
        try {
          namespaceBO = transformNamespace2BO(env, namespace, includeDeletedItems);
          namespaceBOs.add(namespaceBO);
        } catch (Exception e) {
          LOGGER.error("parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}",
              appId, env, clusterName, namespace.getNamespaceName(), e);
          exceptionNamespaces.add(namespace.getNamespaceName());
        } finally {
          latch.countDown();
        }
      });

    }
    try {
      latch.await();
    } catch (InterruptedException e) {
      //ignore
    }

    if(namespaceBOs.size() != namespaces.size()){
       throw new RuntimeException(String
           .format("Parse namespaces error, expected: %s, but actual: %s, cannot get those namespaces: %s", namespaces.size(), namespaceBOs.size(), exceptionNamespaces));
    }

    return namespaceBOs.stream()
        .sorted(Comparator.comparing(o -> o.getBaseInfo().getId()))
        .collect(Collectors.toList());
  }
@Test
  public void testFindNamespace() {

    AppNamespace applicationAppNamespace = mock(AppNamespace.class);
    AppNamespace hermesAppNamespace = mock(AppNamespace.class);

    NamespaceDTO application = new NamespaceDTO();
    application.setId(1);
    application.setClusterName(testClusterName);
    application.setAppId(testAppId);
    application.setNamespaceName(testNamespaceName);

    NamespaceDTO hermes = new NamespaceDTO();
    hermes.setId(2);
    hermes.setClusterName("default");
    hermes.setAppId(testAppId);
    hermes.setNamespaceName("hermes");
    List<NamespaceDTO> namespaces = Arrays.asList(application, hermes);

    ReleaseDTO someRelease = new ReleaseDTO();
    someRelease.setConfigurations("{\"a\":\"123\",\"b\":\"123\"}");

    ItemDTO i1 = new ItemDTO("a", "123", "", 1);
    ItemDTO i2 = new ItemDTO("b", "1", "", 2);
    ItemDTO i3 = new ItemDTO("", "", "#dddd", 3);
    ItemDTO i4 = new ItemDTO("c", "1", "", 4);
    List<ItemDTO> someItems = Arrays.asList(i1, i2, i3, i4);

    when(applicationAppNamespace.getFormat()).thenReturn(ConfigFileFormat.Properties.getValue());
    when(hermesAppNamespace.getFormat()).thenReturn(ConfigFileFormat.XML.getValue());
    when(appNamespaceService.findByAppIdAndName(testAppId, testNamespaceName))
        .thenReturn(applicationAppNamespace);
    when(appNamespaceService.findPublicAppNamespace("hermes")).thenReturn(hermesAppNamespace);
    when(namespaceAPI.findNamespaceByCluster(testAppId, Env.DEV, testClusterName)).thenReturn(namespaces);
    when(releaseService.loadLatestRelease(testAppId, Env.DEV, testClusterName,
                                          testNamespaceName)).thenReturn(someRelease);
    when(releaseService.loadLatestRelease(testAppId, Env.DEV, testClusterName, "hermes")).thenReturn(someRelease);
    when(itemService.findItems(testAppId, Env.DEV, testClusterName, testNamespaceName)).thenReturn(someItems);

    List<NamespaceBO> namespaceVOs = namespaceService.findNamespaceBOs(testAppId, Env.DEV, testClusterName);
    assertEquals(2, namespaceVOs.size());

    when(namespaceAPI.findNamespaceByCluster(testAppId, Env.DEV, testClusterName)).thenReturn(Lists.list(application));
    namespaceVOs = namespaceService.findNamespaceBOs(testAppId, Env.DEV, testClusterName);
    assertEquals(1, namespaceVOs.size());
    NamespaceBO namespaceVO = namespaceVOs.get(0);
    assertEquals(4, namespaceVO.getItems().size());
    assertEquals("a", namespaceVO.getItems().get(0).getItem().getKey());
    assertEquals(2, namespaceVO.getItemModifiedCnt());
    assertEquals(testAppId, namespaceVO.getBaseInfo().getAppId());
    assertEquals(testClusterName, namespaceVO.getBaseInfo().getClusterName());
    assertEquals(testNamespaceName, namespaceVO.getBaseInfo().getNamespaceName());

    ReleaseDTO errorRelease = new ReleaseDTO();
    errorRelease.setConfigurations("\"a\":\"123\",\"b\":\"123\"");
    when(releaseService.loadLatestRelease(testAppId, Env.DEV, testClusterName, testNamespaceName)).thenReturn(errorRelease);
    assertThatExceptionOfType(RuntimeException.class)
        .isThrownBy(()-> namespaceService.findNamespaceBOs(testAppId, Env.DEV, testClusterName))
        .withMessageStartingWith("Parse namespaces error, expected: 1, but actual: 0, cannot get those namespaces: [application]");

  }