This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 1bdad14b75 fix(admin): scope sync cache queries to the changed
namespace (#7267)
1bdad14b75 is described below
commit 1bdad14b75e258c70e02f134aed7db86d9c0876b
Author: Liming Deng <[email protected]>
AuthorDate: Wed Sep 30 11:28:47 2026 +0800
fix(admin): scope sync cache queries to the changed namespace (#7267)
* fix(admin): scope sync cache queries to the changed namespace
* test(admin): pin namespace precedence for dual discovery bindings
---
.../listener/AbstractDataChangedListener.java | 14 ++--
.../admin/mapper/DiscoveryHandlerMapper.java | 8 +++
.../shenyu/admin/service/AiProxyApiKeyService.java | 10 ++-
.../shenyu/admin/service/AppAuthService.java | 8 +++
.../admin/service/DiscoveryUpstreamService.java | 8 +++
.../shenyu/admin/service/MetaDataService.java | 8 +++
.../service/impl/AiProxyApiKeyServiceImpl.java | 10 ++-
.../admin/service/impl/AppAuthServiceImpl.java | 10 ++-
.../service/impl/DiscoveryUpstreamServiceImpl.java | 12 +++-
.../admin/service/impl/MetaDataServiceImpl.java | 5 ++
.../resources/mappers/discovery-handler-sqlmap.xml | 11 +++
.../listener/AbstractDataChangedListenerTest.java | 46 +++++++++++--
.../admin/mapper/DiscoveryNamespaceQueryTest.java | 80 ++++++++++++++++++++++
13 files changed, 213 insertions(+), 17 deletions(-)
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java
index 3045829b0d..e114a3b115 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/AbstractDataChangedListener.java
@@ -359,14 +359,14 @@ public abstract class AbstractDataChangedListener
implements DataChangedListener
* Update selector cache.
*/
protected void updateSelectorCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.SELECTOR, selectorService.listAll(),
namespaceId);
+ this.updateCache(ConfigGroupEnum.SELECTOR,
selectorService.listAllByNamespaceId(namespaceId), namespaceId);
}
/**
* Update rule cache.
*/
protected void updateRuleCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.RULE, ruleService.listAll(),
namespaceId);
+ this.updateCache(ConfigGroupEnum.RULE,
ruleService.listAllByNamespaceId(namespaceId), namespaceId);
}
/**
@@ -380,26 +380,26 @@ public abstract class AbstractDataChangedListener
implements DataChangedListener
* Update app auth cache.
*/
protected void updateAppAuthCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.APP_AUTH, appAuthService.listAll(),
namespaceId);
+ this.updateCache(ConfigGroupEnum.APP_AUTH,
appAuthService.listAllByNamespaceId(namespaceId), namespaceId);
}
/**
* Update meta data cache.
*/
protected void updateMetaDataCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.META_DATA, metaDataService.listAll(),
namespaceId);
+ this.updateCache(ConfigGroupEnum.META_DATA,
metaDataService.listAllByNamespaceId(namespaceId), namespaceId);
}
protected void updateProxySelectorDataCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.PROXY_SELECTOR,
proxySelectorService.listAll(), namespaceId);
+ this.updateCache(ConfigGroupEnum.PROXY_SELECTOR,
proxySelectorService.listAllByNamespaceId(namespaceId), namespaceId);
}
protected void updateDiscoveryUpstreamDataCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.DISCOVER_UPSTREAM,
discoveryUpstreamService.listAll(), namespaceId);
+ this.updateCache(ConfigGroupEnum.DISCOVER_UPSTREAM,
discoveryUpstreamService.listAllByNamespaceId(namespaceId), namespaceId);
}
protected void updateAiProxyApiKeyCache(final String namespaceId) {
- this.updateCache(ConfigGroupEnum.AI_PROXY_API_KEY,
aiProxyApiKeyService.listAll(), namespaceId);
+ this.updateCache(ConfigGroupEnum.AI_PROXY_API_KEY,
aiProxyApiKeyService.listAllByNamespaceId(namespaceId), namespaceId);
}
private <T> ConfigData<T> buildConfigData(final ConfigDataCache config,
final Class<T> dataType) {
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
index 52764fde0b..daab3e91e0 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
@@ -104,6 +104,14 @@ public interface DiscoveryHandlerMapper extends
ExistProvider {
*/
List<DiscoveryHandlerDO> selectAll();
+ /**
+ * Select handlers bound to selectors in a namespace.
+ *
+ * @param namespaceId namespace id
+ * @return discovery handlers
+ */
+ List<DiscoveryHandlerDO> selectAllByNamespaceId(String namespaceId);
+
/**
* selectByDiscoveryId.
*
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AiProxyApiKeyService.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AiProxyApiKeyService.java
index 9381a3641d..5740b97555 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AiProxyApiKeyService.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AiProxyApiKeyService.java
@@ -94,6 +94,14 @@ public interface AiProxyApiKeyService extends
PageService<ProxyApiKeyQuery, Prox
*/
List<org.apache.shenyu.common.dto.ProxyApiKeyData> listAll();
+ /**
+ * List synchronization data in a single namespace.
+ *
+ * @param namespaceId namespace id
+ * @return synchronization data
+ */
+ List<org.apache.shenyu.common.dto.ProxyApiKeyData>
listAllByNamespaceId(String namespaceId);
+
/**
* Publish REFRESH event contains all proxy api key data (all namespaces).
*/
@@ -105,4 +113,4 @@ public interface AiProxyApiKeyService extends
PageService<ProxyApiKeyQuery, Prox
* @param namespaceId namespace id
*/
void syncDataByNamespaceId(String namespaceId);
-}
\ No newline at end of file
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
index 161f7c2960..79544b4964 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java
@@ -139,6 +139,14 @@ public interface AppAuthService extends
PageService<AppAuthQuery, AppAuthVO> {
*/
List<AppAuthData> listAll();
+ /**
+ * List synchronization data in a single namespace.
+ *
+ * @param namespaceId namespace id
+ * @return synchronization data
+ */
+ List<AppAuthData> listAllByNamespaceId(String namespaceId);
+
/**
* List all vo list.
*
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
index 047cd1821a..b99a51bda3 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
@@ -76,6 +76,14 @@ public interface DiscoveryUpstreamService {
*/
List<DiscoverySyncData> listAll();
+ /**
+ * List synchronization data in a single namespace.
+ *
+ * @param namespaceId namespace id
+ * @return synchronization data
+ */
+ List<DiscoverySyncData> listAllByNamespaceId(String namespaceId);
+
/**
* list all data.
*
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java
index 39d06fc1a4..dab4ec90cc 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java
@@ -97,6 +97,14 @@ public interface MetaDataService {
*/
List<MetaData> listAll();
+ /**
+ * List synchronization data in a single namespace.
+ *
+ * @param namespaceId namespace id
+ * @return synchronization data
+ */
+ List<MetaData> listAllByNamespaceId(String namespaceId);
+
/**
* List all vo list.
*
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AiProxyApiKeyServiceImpl.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AiProxyApiKeyServiceImpl.java
index 1d1c84afa9..d9636bf79d 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AiProxyApiKeyServiceImpl.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AiProxyApiKeyServiceImpl.java
@@ -219,7 +219,15 @@ public class AiProxyApiKeyServiceImpl implements
AiProxyApiKeyService {
@Override
public List<ProxyApiKeyData> listAll() {
- List<ProxyApiKeyDO> all = mapper.selectAll();
+ return buildSyncData(mapper.selectAll());
+ }
+
+ @Override
+ public List<ProxyApiKeyData> listAllByNamespaceId(final String
namespaceId) {
+ return buildSyncData(mapper.selectAllByNamespaceId(namespaceId));
+ }
+
+ private List<ProxyApiKeyData> buildSyncData(final List<ProxyApiKeyDO> all)
{
if (CollectionUtils.isEmpty(all)) {
return java.util.Collections.emptyList();
}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
index c24db4b6a9..0aeb8373d5 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java
@@ -580,7 +580,15 @@ public class AppAuthServiceImpl implements AppAuthService {
@Override
public List<AppAuthData> listAll() {
- List<AppAuthDO> appAuthDOList = appAuthMapper.selectAll();
+ return buildSyncData(appAuthMapper.selectAll());
+ }
+
+ @Override
+ public List<AppAuthData> listAllByNamespaceId(final String namespaceId) {
+ return
buildSyncData(appAuthMapper.selectAllByNamespaceId(namespaceId));
+ }
+
+ private List<AppAuthData> buildSyncData(final List<AppAuthDO>
appAuthDOList) {
if (CollectionUtils.isEmpty(appAuthDOList)) {
return new ArrayList<>();
}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
index 2c7e154e91..bf379d40e7 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
@@ -179,7 +179,15 @@ public class DiscoveryUpstreamServiceImpl implements
DiscoveryUpstreamService {
@Override
public List<DiscoverySyncData> listAll() {
- List<DiscoveryHandlerDO> discoveryHandlerDOS =
discoveryHandlerMapper.selectAll();
+ return buildSyncData(discoveryHandlerMapper.selectAll());
+ }
+
+ @Override
+ public List<DiscoverySyncData> listAllByNamespaceId(final String
namespaceId) {
+ return
buildSyncData(discoveryHandlerMapper.selectAllByNamespaceId(namespaceId));
+ }
+
+ private List<DiscoverySyncData> buildSyncData(final
List<DiscoveryHandlerDO> discoveryHandlerDOS) {
return discoveryHandlerDOS.stream().map(d -> {
DiscoveryRelDO discoveryRelDO =
discoveryRelMapper.selectByDiscoveryHandlerId(d.getId());
DiscoverySyncData discoverySyncData = new DiscoverySyncData();
@@ -189,11 +197,13 @@ public class DiscoveryUpstreamServiceImpl implements
DiscoveryUpstreamService {
discoverySyncData.setSelectorId(selectorId);
SelectorDO selectorDO = selectorMapper.selectById(selectorId);
discoverySyncData.setSelectorName(selectorDO.getSelectorName());
+ discoverySyncData.setNamespaceId(selectorDO.getNamespaceId());
} else {
String proxySelectorId = discoveryRelDO.getProxySelectorId();
discoverySyncData.setSelectorId(proxySelectorId);
ProxySelectorDO proxySelectorDO =
proxySelectorMapper.selectById(proxySelectorId);
discoverySyncData.setSelectorName(proxySelectorDO.getName());
+
discoverySyncData.setNamespaceId(proxySelectorDO.getNamespaceId());
}
List<DiscoveryUpstreamData> discoveryUpstreamDataList =
discoveryUpstreamMapper.selectByDiscoveryHandlerId(d.getId()).stream()
.map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList());
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java
index 150c8a9c7c..9876bc9778 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java
@@ -183,6 +183,11 @@ public class MetaDataServiceImpl implements
MetaDataService {
return ListUtil.map(metaDataMapper.selectAll(),
MetaDataTransfer.INSTANCE::mapToData);
}
+ @Override
+ public List<MetaData> listAllByNamespaceId(final String namespaceId) {
+ return ListUtil.map(metaDataMapper.findAllByNamespaceId(namespaceId),
MetaDataTransfer.INSTANCE::mapToData);
+ }
+
@Override
public List<MetaDataVO> listAllData() {
return ListUtil.map(metaDataMapper.selectAll(),
MetaDataTransfer.INSTANCE::mapToVO);
diff --git
a/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
b/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
index 6cbb6a91d6..f5c69ad640 100644
--- a/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
+++ b/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
@@ -69,6 +69,17 @@
from discovery_handler
</select>
+ <select id="selectAllByNamespaceId" resultMap="BaseResultMap">
+ SELECT <include refid="Base_Column_List"/>
+ FROM discovery_handler
+ WHERE id IN (
+ SELECT discovery_handler_id FROM discovery_rel
+ WHERE selector_id IN (SELECT id FROM selector WHERE namespace_id =
#{namespaceId})
+ OR ((selector_id IS NULL OR selector_id = '')
+ AND proxy_selector_id IN (SELECT id FROM proxy_selector
WHERE namespace_id = #{namespaceId}))
+ )
+ </select>
+
<select id="selectByDiscoveryId" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
diff --git
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java
index cd2ed67f13..8227b4d600 100644
---
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java
+++
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/listener/AbstractDataChangedListenerTest.java
@@ -49,9 +49,12 @@ import java.util.concurrent.ConcurrentMap;
import static
org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.apache.shenyu.admin.service.AiProxyApiKeyService;
@@ -123,19 +126,19 @@ public final class AbstractDataChangedListenerTest {
aiProxyApiKeyServiceField.set(listener, aiProxyApiKeyService);
List<AppAuthData> appAuthDatas =
Lists.newArrayList(mock(AppAuthData.class));
- when(appAuthService.listAll()).thenReturn(appAuthDatas);
+
when(appAuthService.listAllByNamespaceId(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(appAuthDatas);
List<PluginData> pluginDatas =
Lists.newArrayList(mock(PluginData.class));
when(namespacePluginService.listAll(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(pluginDatas);
List<RuleData> ruleDatas = Lists.newArrayList(mock(RuleData.class));
- when(ruleService.listAll()).thenReturn(ruleDatas);
+
when(ruleService.listAllByNamespaceId(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(ruleDatas);
List<SelectorData> selectorDatas =
Lists.newArrayList(mock(SelectorData.class));
- when(selectorService.listAll()).thenReturn(selectorDatas);
+
when(selectorService.listAllByNamespaceId(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(selectorDatas);
List<MetaData> metaDatas = Lists.newArrayList(mock(MetaData.class));
- when(metaDataService.listAll()).thenReturn(metaDatas);
+
when(metaDataService.listAllByNamespaceId(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(metaDatas);
List<ProxySelectorData> proxySelectorDatas =
Lists.newArrayList(mock(ProxySelectorData.class));
- when(proxySelectorService.listAll()).thenReturn(proxySelectorDatas);
+
when(proxySelectorService.listAllByNamespaceId(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(proxySelectorDatas);
List<DiscoverySyncData> discoverySyncDatas =
Lists.newArrayList(mock(DiscoverySyncData.class));
-
when(discoveryUpstreamService.listAll()).thenReturn(discoverySyncDatas);
+
when(discoveryUpstreamService.listAllByNamespaceId(SYS_DEFAULT_NAMESPACE_ID)).thenReturn(discoverySyncDatas);
List<NamespaceVO> list = new ArrayList<>();
NamespaceVO namespaceVO = new NamespaceVO();
namespaceVO.setNamespaceId(SYS_DEFAULT_NAMESPACE_ID);
@@ -146,6 +149,37 @@ public final class AbstractDataChangedListenerTest {
listener.getCache().clear();
}
+ @Test
+ void refreshesOnlyTheRequestedNamespaceForEverySyncGroup() {
+ for (String namespace : new String[]{"namespace-a", "namespace-b"}) {
+
when(selectorService.listAllByNamespaceId(namespace)).thenReturn(java.util.Collections.singletonList(
+
SelectorData.builder().id(namespace).namespaceId(namespace).build()));
+ listener.updateSelectorCache(namespace);
+ listener.updateRuleCache(namespace);
+ listener.updateAppAuthCache(namespace);
+ listener.updateMetaDataCache(namespace);
+ listener.updateProxySelectorDataCache(namespace);
+ listener.updateDiscoveryUpstreamDataCache(namespace);
+ listener.updateAiProxyApiKeyCache(namespace);
+ verify(selectorService).listAllByNamespaceId(namespace);
+ verify(ruleService).listAllByNamespaceId(namespace);
+ verify(appAuthService).listAllByNamespaceId(namespace);
+ verify(metaDataService).listAllByNamespaceId(namespace);
+ verify(proxySelectorService).listAllByNamespaceId(namespace);
+ verify(discoveryUpstreamService).listAllByNamespaceId(namespace);
+ verify(aiProxyApiKeyService).listAllByNamespaceId(namespace);
+ SelectorData cached = (SelectorData)
listener.fetchConfig(ConfigGroupEnum.SELECTOR, namespace).getData().get(0);
+ assertEquals(namespace, cached.getNamespaceId());
+ }
+ verify(selectorService, never()).listAll();
+ verify(ruleService, never()).listAll();
+ verify(appAuthService, never()).listAll();
+ verify(metaDataService, never()).listAll();
+ verify(proxySelectorService, never()).listAll();
+ verify(discoveryUpstreamService, never()).listAll();
+ verify(aiProxyApiKeyService, never()).listAll();
+ }
+
@AfterEach
public void cleanUp() {
listener.getCache().clear();
diff --git
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/DiscoveryNamespaceQueryTest.java
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/DiscoveryNamespaceQueryTest.java
new file mode 100644
index 0000000000..4e247eefd5
--- /dev/null
+++
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/DiscoveryNamespaceQueryTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.shenyu.admin.mapper;
+
+import org.apache.ibatis.builder.xml.XMLMapperBuilder;
+import org.apache.ibatis.mapping.Environment;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
+import org.apache.shenyu.admin.model.entity.DiscoveryHandlerDO;
+import org.junit.jupiter.api.Test;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+
+import java.io.InputStream;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class DiscoveryNamespaceQueryTest {
+
+ @Test
+ void scopesRegularAndProxyHandlersAtTheDatabase() throws Exception {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource(
+ "jdbc:h2:mem:discovery-namespace-" + UUID.randomUUID() +
";DB_CLOSE_DELAY=-1;MODE=MySQL", "sa", "");
+ JdbcTemplate jdbc = new JdbcTemplate(dataSource);
+ try {
+ new ResourceDatabasePopulator(new
ClassPathResource("sql-script/h2/schema.sql")).execute(dataSource);
+ for (String namespace : new String[]{"a", "b"}) {
+ jdbc.update("INSERT INTO selector (id, plugin_id,
selector_name, match_mode, selector_type, sort_code, enabled, loged, continued,
match_restful, namespace_id) "
+ + "VALUES (?, 'p', 'selector', 0, 0, 0, 1, 0, 0, 0,
?)", "s-" + namespace, namespace);
+ jdbc.update("INSERT INTO discovery_handler (id, discovery_id,
handler) VALUES (?, 'discovery', '{}')", "h-" + namespace);
+ jdbc.update("INSERT INTO discovery_rel (id, plugin_name,
discovery_handler_id, selector_id) VALUES (?, 'divide', ?, ?)",
+ "r-" + namespace, "h-" + namespace, "s-" + namespace);
+ }
+ jdbc.update("INSERT INTO proxy_selector (id, name, plugin_name,
type, forward_port, namespace_id) VALUES ('proxy-a', 'proxy', 'tcp', 'tcp',
10000, 'a')");
+ jdbc.update("INSERT INTO discovery_handler (id, discovery_id,
handler) VALUES ('h-proxy', 'discovery', '{}')");
+ jdbc.update("INSERT INTO discovery_rel (id, plugin_name,
discovery_handler_id, proxy_selector_id) VALUES ('r-proxy', 'tcp', 'h-proxy',
'proxy-a')");
+ jdbc.update("INSERT INTO discovery_handler (id, discovery_id,
handler) VALUES ('orphan', 'discovery', '{}')");
+ // When both ids exist, the selector namespace wins even if the
proxy belongs elsewhere.
+ jdbc.update("INSERT INTO discovery_handler (id, discovery_id,
handler) VALUES ('h-both', 'discovery', '{}')");
+ jdbc.update("INSERT INTO discovery_rel (id, plugin_name,
discovery_handler_id, selector_id, proxy_selector_id) "
+ + "VALUES ('r-both', 'divide', 'h-both', 's-b',
'proxy-a')");
+ Configuration configuration = new Configuration(new
Environment("test", new JdbcTransactionFactory(), dataSource));
+ try (InputStream input = new
ClassPathResource("mappers/discovery-handler-sqlmap.xml").getInputStream()) {
+ new XMLMapperBuilder(input, configuration,
"discovery-handler", configuration.getSqlFragments()).parse();
+ }
+ try (SqlSession session = new
SqlSessionFactoryBuilder().build(configuration).openSession()) {
+ DiscoveryHandlerMapper mapper =
session.getMapper(DiscoveryHandlerMapper.class);
+ assertEquals(Set.of("h-a", "h-proxy"),
mapper.selectAllByNamespaceId("a").stream().map(DiscoveryHandlerDO::getId).collect(Collectors.toSet()));
+ assertEquals(Set.of("h-b", "h-both"),
mapper.selectAllByNamespaceId("b").stream().map(DiscoveryHandlerDO::getId).collect(Collectors.toSet()));
+ assertTrue(mapper.selectAllByNamespaceId("missing").isEmpty());
+ }
+ } finally {
+ jdbc.execute("SHUTDOWN");
+ }
+ }
+}