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 8a76a026fd   fix: register and clean up API runtime resources (#7017)
8a76a026fd is described below

commit 8a76a026fd676b83e692413d2d392ebe1b68c4f6
Author: Southern <[email protected]>
AuthorDate: Wed Sep 2 06:56:21 2026 +0800

      fix: register and clean up API runtime resources (#7017)
    
    - After the API is created successfully, call the 'register' function to 
publish the associated selector/rule/metadata.
      - After the API is deleted successfully, call the 'removeRegister' 
function to clean up the associated runtime data.
      - When deleting by API path, the cleanup is executed synchronously.
      - Add protection for cases where extension data or context path is 
missing.
      - Add tests for API deletion cleanup and scenarios where the API does not 
exist.
    
    Co-authored-by: aias00 <[email protected]>
---
 .../shenyu/admin/service/impl/ApiServiceImpl.java  |  6 ++++
 .../shenyu/admin/service/ApiServiceTest.java       | 41 ++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ApiServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ApiServiceImpl.java
index ad05dbc788..6386166fe2 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ApiServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ApiServiceImpl.java
@@ -152,6 +152,7 @@ public class ApiServiceImpl implements ApiService {
                         .build()).collect(Collectors.toList());
                 tagRelationMapper.batchInsert(tags);
             }
+            register(apiDO);
         }
         return ShenyuResultMessage.CREATE_SUCCESS;
     }
@@ -191,6 +192,9 @@ public class ApiServiceImpl implements ApiService {
     private void register(final ApiDO apiDO) {
         //register selector/rule/metadata if necessary
         final ApiDocRegisterDTO.ApiExt ext = 
GsonUtils.getInstance().fromJson(apiDO.getExt(), 
ApiDocRegisterDTO.ApiExt.class);
+        if (Objects.isNull(ext) || 
StringUtils.isBlank(apiDO.getContextPath())) {
+            return;
+        }
         RegisterClientServerDisruptorPublisher publisher = 
RegisterClientServerDisruptorPublisher.getInstance();
         final String contextPath = apiDO.getContextPath();
         final String path = apiDO.getApiPath();
@@ -228,6 +232,7 @@ public class ApiServiceImpl implements ApiService {
         final int deleteRows = this.apiMapper.deleteByIds(apiIds);
         if (deleteRows > 0) {
             tagRelationMapper.deleteByApiIds(apiIds);
+            apis.forEach(this::removeRegister);
         }
         return StringUtils.EMPTY;
     }
@@ -281,6 +286,7 @@ public class ApiServiceImpl implements ApiService {
             final int deleteRows = this.apiMapper.deleteByIds(apiIds);
             if (deleteRows > 0) {
                 tagRelationMapper.deleteByApiIds(apiIds);
+                apiDOs.forEach(this::removeRegister);
             }
             return deleteRows;
         }
diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ApiServiceTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ApiServiceTest.java
index 7ffc2c87b0..5c789f5482 100644
--- 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ApiServiceTest.java
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ApiServiceTest.java
@@ -23,12 +23,16 @@ import org.apache.shenyu.admin.mapper.TagMapper;
 import org.apache.shenyu.admin.mapper.TagRelationMapper;
 import org.apache.shenyu.admin.model.dto.ApiDTO;
 import org.apache.shenyu.admin.model.entity.ApiDO;
+import org.apache.shenyu.admin.model.entity.MetaDataDO;
+import org.apache.shenyu.admin.model.entity.SelectorDO;
 import org.apache.shenyu.admin.model.page.CommonPager;
 import org.apache.shenyu.admin.model.page.PageParameter;
 import org.apache.shenyu.admin.model.query.ApiQuery;
 import org.apache.shenyu.admin.model.vo.ApiVO;
+import org.apache.shenyu.admin.model.vo.RuleVO;
 import org.apache.shenyu.admin.service.impl.ApiServiceImpl;
 import org.apache.shenyu.admin.utils.ShenyuResultMessage;
+import org.apache.shenyu.common.constant.AdminConstants;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -47,8 +51,14 @@ import java.util.stream.IntStream;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static 
org.apache.shenyu.common.constant.Constants.SYS_DEFAULT_NAMESPACE_ID;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 /**
@@ -99,6 +109,37 @@ public final class ApiServiceTest {
         assertEquals(StringUtils.EMPTY, 
apiService.delete(Collections.singletonList("123")));
     }
 
+    @Test
+    public void testDeleteCleansRegisteredResources() {
+        RuleVO rule = new RuleVO();
+        rule.setId("rule-1");
+        SelectorDO selector = new SelectorDO();
+        selector.setId("selector-1");
+        MetaDataDO metadata = new MetaDataDO();
+        metadata.setId("metadata-1");
+        ApiDO apiDO = buildApiDO("123");
+        
when(apiMapper.selectByIds(Collections.singletonList("123"))).thenReturn(Collections.singletonList(apiDO));
+        
when(apiMapper.deleteByIds(Collections.singletonList("123"))).thenReturn(1);
+        
when(ruleService.searchByCondition(any())).thenReturn(Collections.singletonList(rule));
+        
when(selectorService.findByNameAndPluginNamesAndNamespaceId(anyString(), 
anyList(), anyString()))
+                .thenReturn(Collections.singletonList(selector));
+        
when(ruleService.findBySelectorId("selector-1")).thenReturn(Collections.emptyList());
+        when(metaDataService.findByPathAndNamespaceId(apiDO.getApiPath(), 
SYS_DEFAULT_NAMESPACE_ID)).thenReturn(metadata);
+
+        apiService.delete(Collections.singletonList("123"));
+
+        verify(ruleService, 
times(1)).deleteByIdsAndNamespaceId(Collections.singletonList("rule-1"), 
SYS_DEFAULT_NAMESPACE_ID);
+        verify(selectorService, 
times(1)).deleteByNamespaceId(Collections.singletonList("selector-1"), 
SYS_DEFAULT_NAMESPACE_ID);
+        verify(metaDataService, 
times(1)).deleteByIdsAndNamespaceId(Collections.singletonList("metadata-1"), 
SYS_DEFAULT_NAMESPACE_ID);
+    }
+
+    @Test
+    public void testDeleteWhenApiDoesNotExist() {
+        
when(apiMapper.selectByIds(Collections.singletonList("missing"))).thenReturn(Collections.emptyList());
+
+        assertEquals(AdminConstants.SYS_API_ID_NOT_EXIST, 
apiService.delete(Collections.singletonList("missing")));
+    }
+
     @Test
     public void testFindById() {
         String id = "123";

Reply via email to