update modules/kbase: add 5 mod 9 del 1 files

This commit is contained in:
jack ning
2025-05-17 09:38:07 +08:00
parent 222a735fd6
commit f30fb09078
13 changed files with 647 additions and 87 deletions

View File

@@ -0,0 +1,91 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-05-17 11:00:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-05-17 09:12:31
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.kbase.faq;
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
/**
* FAQ索引批量测试工具
* 用于模拟批量处理FAQ创建事件测试消息队列的有效性
*/
@Slf4j
@Component
public class FaqBulkIndexTester {
@Autowired
private FaqMessageService faqMessageService;
@Autowired
private FaqRepository faqRepository;
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
/**
* 测试批量发送FAQ到索引队列
* 每个FAQ都分别发送一条索引消息
*
* @param faqCount 测试的FAQ数量
*/
public void testBulkFaqIndexing(int faqCount) {
log.info("开始测试批量FAQ索引, 数量: {}", faqCount);
// 从数据库获取前N个FAQ
var faqs = faqRepository.findAll().stream().limit(faqCount).toList();
if (faqs.isEmpty()) {
log.warn("没有找到FAQ记录无法进行批量索引测试");
return;
}
log.info("共找到{}个FAQ记录用于测试", faqs.size());
// 多线程并发发送消息
for (FaqEntity faq : faqs) {
executorService.submit(() -> {
try {
log.debug("发送FAQ索引请求: {}", faq.getUid());
faqMessageService.sendToIndexQueue(faq.getUid());
} catch (Exception e) {
log.error("发送FAQ索引消息失败: {}", e.getMessage(), e);
}
});
}
log.info("批量索引测试任务已提交,时间: {}", LocalDateTime.now());
}
/**
* 清理资源
*/
@PreDestroy
public void destroy() {
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* @Author: jackning 270580156@qq.com
* @Date: 2025-05-17 11:10:00
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-05-17 11:10:00
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 联系270580156@qq.com
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
*/
package com.bytedesk.kbase.faq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* FAQ索引测试控制器
* 用于手动触发FAQ索引测试
*/
@Tag(name = "FAQ索引测试")
@RestController
@RequestMapping("/api/v1/kbase/faq/test")
public class FaqIndexTestController {
@Autowired
private FaqBulkIndexTester faqBulkIndexTester;
@Operation(summary = "测试批量FAQ索引")
@PostMapping("/bulk-index")
public ResponseEntity<String> testBulkFaqIndexing(
@RequestParam(value = "count", defaultValue = "10") int count) {
faqBulkIndexTester.testBulkFaqIndexing(count);
return ResponseEntity.ok("FAQ批量索引测试已启动索引数量: " + count);
}
}

View File

@@ -1,16 +1,31 @@
package com.bytedesk.kbase.faq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import lombok.extern.slf4j.Slf4j;
/**
* FAQ消息队列测试类
* 包含集成测试和单元测试
*/
@Slf4j
@SpringBootTest
@@ -22,6 +37,97 @@ public class FaqMessageQueueTests {
@Autowired
private FaqRepository faqRepository;
/**
* 测试客户端确认模式的消息队列处理
*/
@ExtendWith(MockitoExtension.class)
static class ClientAcknowledgeTests {
@Mock
private FaqElasticService faqElasticService;
@Mock
private FaqVectorService faqVectorService;
@Mock
private FaqRestService faqRestService;
@InjectMocks
private FaqIndexConsumer faqIndexConsumer;
/**
* 测试成功处理消息时确认消息
*/
@Test
void testMessageAcknowledgmentOnSuccess() throws Exception {
// 准备测试数据
String faqUid = "test-faq-uid";
FaqIndexMessage indexMessage = new FaqIndexMessage(faqUid, "index", true, true);
Message jmsMessage = mock(Message.class);
// 模拟FAQ存在
FaqEntity mockFaq = new FaqEntity();
mockFaq.setUid(faqUid);
when(faqRestService.findByUid(faqUid)).thenReturn(Optional.of(mockFaq));
// 调用被测试的方法
faqIndexConsumer.processIndexMessage(jmsMessage, indexMessage);
// 验证消息被确认
verify(jmsMessage, times(1)).acknowledge();
}
/**
* 测试处理失败时不确认消息
*/
@Test
void testNoAcknowledgmentOnFailure() throws Exception {
// 准备测试数据
String faqUid = "test-faq-uid";
FaqIndexMessage indexMessage = new FaqIndexMessage(faqUid, "index", true, true);
Message jmsMessage = mock(Message.class);
// 模拟FAQ存在
FaqEntity mockFaq = new FaqEntity();
mockFaq.setUid(faqUid);
when(faqRestService.findByUid(faqUid)).thenReturn(Optional.of(mockFaq));
// 模拟索引操作抛出异常
doThrow(new RuntimeException("模拟索引失败")).when(faqElasticService).indexFaq(any());
// 调用被测试的方法
faqIndexConsumer.processIndexMessage(jmsMessage, indexMessage);
// 验证消息没有被确认
verify(jmsMessage, never()).acknowledge();
}
/**
* 测试确认消息时出现异常的情况
*/
@Test
void testAcknowledgmentException() throws Exception {
// 准备测试数据
String faqUid = "test-faq-uid";
FaqIndexMessage indexMessage = new FaqIndexMessage(faqUid, "index", true, false);
Message jmsMessage = mock(Message.class);
// 模拟FAQ存在
FaqEntity mockFaq = new FaqEntity();
mockFaq.setUid(faqUid);
when(faqRestService.findByUid(faqUid)).thenReturn(Optional.of(mockFaq));
// 模拟确认消息时抛出异常
doThrow(new JMSException("模拟确认失败")).when(jmsMessage).acknowledge();
// 调用被测试的方法 - 不应抛出异常
faqIndexConsumer.processIndexMessage(jmsMessage, indexMessage);
// 验证尝试确认消息
verify(jmsMessage, times(1)).acknowledge();
}
}
/**
* 测试发送单个FAQ到索引队列
*/