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 bca690634a fix(admin): skip orphan discovery bindings during full sync 
(#7250)
bca690634a is described below

commit bca690634a0e22955480cca0a7a35dbeb5555632
Author: Liming Deng <[email protected]>
AuthorDate: Thu Oct 1 06:28:33 2026 +0800

    fix(admin): skip orphan discovery bindings during full sync (#7250)
---
 .../service/impl/DiscoveryUpstreamServiceImpl.java | 18 +++++++++-
 .../service/DiscoveryUpstreamServiceTest.java      | 39 ++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

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 fca9a06012..943ba7386d 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
@@ -46,6 +46,8 @@ import org.apache.shenyu.admin.utils.Assert;
 import org.apache.shenyu.admin.utils.ShenyuResultMessage;
 import org.apache.shenyu.common.dto.DiscoverySyncData;
 import org.apache.shenyu.common.dto.DiscoveryUpstreamData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.TransactionSynchronization;
@@ -63,6 +65,8 @@ import java.util.stream.Collectors;
 @Service
 public class DiscoveryUpstreamServiceImpl implements DiscoveryUpstreamService {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(DiscoveryUpstreamServiceImpl.class);
+
     private final DiscoveryUpstreamMapper discoveryUpstreamMapper;
 
     private final DiscoveryHandlerMapper discoveryHandlerMapper;
@@ -192,18 +196,30 @@ public class DiscoveryUpstreamServiceImpl implements 
DiscoveryUpstreamService {
     private List<DiscoverySyncData> buildSyncData(final 
List<DiscoveryHandlerDO> discoveryHandlerDOS) {
         return discoveryHandlerDOS.stream().map(d -> {
             DiscoveryRelDO discoveryRelDO = 
discoveryRelMapper.selectByDiscoveryHandlerId(d.getId());
+            if (Objects.isNull(discoveryRelDO)) {
+                LOG.warn("Skipping discovery handler {} without a relation", 
d.getId());
+                return null;
+            }
             DiscoverySyncData discoverySyncData = new DiscoverySyncData();
             discoverySyncData.setPluginName(discoveryRelDO.getPluginName());
             if (StringUtils.hasLength(discoveryRelDO.getSelectorId())) {
                 String selectorId = discoveryRelDO.getSelectorId();
                 discoverySyncData.setSelectorId(selectorId);
                 SelectorDO selectorDO = selectorMapper.selectById(selectorId);
+                if (Objects.isNull(selectorDO)) {
+                    LOG.warn("Skipping discovery handler {} with missing 
selector {}", d.getId(), selectorId);
+                    return null;
+                }
                 
discoverySyncData.setSelectorName(selectorDO.getSelectorName());
                 discoverySyncData.setNamespaceId(selectorDO.getNamespaceId());
             } else {
                 String proxySelectorId = discoveryRelDO.getProxySelectorId();
                 discoverySyncData.setSelectorId(proxySelectorId);
                 ProxySelectorDO proxySelectorDO = 
proxySelectorMapper.selectById(proxySelectorId);
+                if (Objects.isNull(proxySelectorDO)) {
+                    LOG.warn("Skipping discovery handler {} with missing proxy 
selector {}", d.getId(), proxySelectorId);
+                    return null;
+                }
                 discoverySyncData.setSelectorName(proxySelectorDO.getName());
                 
discoverySyncData.setNamespaceId(proxySelectorDO.getNamespaceId());
             }
@@ -211,7 +227,7 @@ public class DiscoveryUpstreamServiceImpl implements 
DiscoveryUpstreamService {
                     
.map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList());
             discoverySyncData.setUpstreamDataList(discoveryUpstreamDataList);
             return discoverySyncData;
-        }).collect(Collectors.toList());
+        }).filter(Objects::nonNull).collect(Collectors.toList());
     }
 
     @Override
diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryUpstreamServiceTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryUpstreamServiceTest.java
index cd1de5a753..d8a5176663 100644
--- 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryUpstreamServiceTest.java
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/DiscoveryUpstreamServiceTest.java
@@ -176,6 +176,45 @@ public final class DiscoveryUpstreamServiceTest {
         assertEquals(dataList.size(), list.size());
     }
 
+    @Test
+    public void testListAllSkipsOrphansAndKeepsValidBindings() {
+        DiscoveryHandlerDO noRelation = buildDiscoveryHandlerDO();
+        noRelation.setId("no-relation");
+        DiscoveryHandlerDO missingSelector = buildDiscoveryHandlerDO();
+        missingSelector.setId("missing-selector");
+        DiscoveryHandlerDO missingProxy = buildDiscoveryHandlerDO();
+        missingProxy.setId("missing-proxy");
+        DiscoveryHandlerDO validSelector = buildDiscoveryHandlerDO();
+        validSelector.setId("valid-selector");
+        DiscoveryHandlerDO validProxy = buildDiscoveryHandlerDO();
+        validProxy.setId("valid-proxy");
+        
when(discoveryHandlerMapper.selectAll()).thenReturn(List.of(noRelation, 
missingSelector, validSelector, missingProxy, validProxy));
+        
when(discoveryRelMapper.selectByDiscoveryHandlerId("no-relation")).thenReturn(null);
+        DiscoveryRelDO staleSelectorRel = buildDiscoveryRelDO();
+        staleSelectorRel.setSelectorId("deleted-selector");
+        
when(discoveryRelMapper.selectByDiscoveryHandlerId("missing-selector")).thenReturn(staleSelectorRel);
+        DiscoveryRelDO staleProxyRel = buildDiscoveryRelDO();
+        staleProxyRel.setProxySelectorId("deleted-proxy");
+        
when(discoveryRelMapper.selectByDiscoveryHandlerId("missing-proxy")).thenReturn(staleProxyRel);
+        DiscoveryRelDO selectorRel = buildDiscoveryRelDO();
+        selectorRel.setSelectorId("selector_1");
+        
when(discoveryRelMapper.selectByDiscoveryHandlerId("valid-selector")).thenReturn(selectorRel);
+        
when(selectorMapper.selectById("selector_1")).thenReturn(buildSelectorDO());
+        when(selectorMapper.selectById("deleted-selector")).thenReturn(null);
+        DiscoveryRelDO proxyRel = buildDiscoveryRelDO();
+        proxyRel.setProxySelectorId("proxy_1");
+        
when(discoveryRelMapper.selectByDiscoveryHandlerId("valid-proxy")).thenReturn(proxyRel);
+        
when(proxySelectorMapper.selectById("proxy_1")).thenReturn(buildProxySelectorDO());
+        when(proxySelectorMapper.selectById("deleted-proxy")).thenReturn(null);
+        List<DiscoverySyncData> result = discoveryUpstreamService.listAll();
+        assertEquals(2, result.size());
+        assertEquals("selector_1", result.get(0).getSelectorId());
+        assertEquals("proxy_1", result.get(1).getSelectorId());
+        verify(discoveryUpstreamMapper, 
never()).selectByDiscoveryHandlerId("no-relation");
+        verify(discoveryUpstreamMapper, 
never()).selectByDiscoveryHandlerId("missing-selector");
+        verify(discoveryUpstreamMapper, 
never()).selectByDiscoveryHandlerId("missing-proxy");
+    }
+
     @Test
     public void testListAllData() {
         List<DiscoveryUpstreamDO> list = 
Collections.singletonList(buildDiscoveryUpstreamDO(""));

Reply via email to