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");
+        }
+    }
+}

Reply via email to