Compare commits

...
Author SHA1 Message Date
Tomsun28 4763774b66 Merge branch 'master' into 0725-yuluo/fix 2026-07-26 14:23:40 +08:00
Duansg d689faced5 Merge branch 'master' into 0725-yuluo/fix 2026-07-25 20:22:23 +08:00
yuluo-yx 72ecd8eb71 feat
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2026-07-25 18:32:48 +08:00
shown 57d3897501 Update ConversationServiceImpl.java
Signed-off-by: shown <yuluo08290126@gmail.com>
2026-07-25 18:24:47 +08:00
yuluo-yx 1aab0159be fix(ai): remove SOP schedules when deleting conversations
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
2026-07-25 18:22:52 +08:00
2 changed files with 34 additions and 0 deletions
@@ -23,6 +23,7 @@ import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.ai.dao.ChatConversationDao;
import org.apache.hertzbeat.ai.dao.ChatMessageDao;
import org.apache.hertzbeat.ai.dao.SopScheduleDao;
import org.apache.hertzbeat.ai.pojo.dto.ChatRequestContext;
import org.apache.hertzbeat.ai.pojo.dto.ChatResponseChunk;
import org.apache.hertzbeat.ai.pojo.dto.SecurityData;
@@ -57,6 +58,9 @@ public class ConversationServiceImpl implements ConversationService {
@Autowired
private ChatMessageDao messageDao;
@Autowired
private SopScheduleDao sopScheduleDao;
@Autowired
private ChatClientProviderService chatClientProviderService;
@@ -197,6 +201,8 @@ public class ConversationServiceImpl implements ConversationService {
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteConversation(Long conversationId) {
// Delete associated schedules first to prevent tasks from writing orphaned messages.
sopScheduleDao.deleteByConversationId(conversationId);
List<ChatMessage> messages = messageDao.findByConversationIdOrderByGmtCreateAsc(conversationId);
if (!messages.isEmpty()) {
messageDao.deleteAll(messages);
@@ -20,6 +20,7 @@ package org.apache.hertzbeat.ai.service.impl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -30,6 +31,7 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.hertzbeat.ai.dao.ChatConversationDao;
import org.apache.hertzbeat.ai.dao.ChatMessageDao;
import org.apache.hertzbeat.ai.dao.SopScheduleDao;
import org.apache.hertzbeat.ai.pojo.dto.ChatRequestContext;
import org.apache.hertzbeat.ai.pojo.dto.ChatResponseChunk;
import org.apache.hertzbeat.ai.service.ChatClientProviderService;
@@ -40,6 +42,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.codec.ServerSentEvent;
@@ -59,6 +62,9 @@ class ConversationServiceImplTest {
@Mock
private ChatMessageDao messageDao;
@Mock
private SopScheduleDao sopScheduleDao;
@Mock
private ChatClientProviderService chatClientProviderService;
@@ -116,4 +122,26 @@ class ConversationServiceImplTest {
assertEquals(history, contextCaptor.getValue().getConversationHistory());
assertEquals(subject, contextCaptor.getValue().getSubject());
}
/**
* Deleting a conversation must remove its schedules before they can push more messages.
*/
@Test
void deleteConversationShouldRemoveSchedulesMessagesAndConversationInOrder() {
ChatMessage message = ChatMessage.builder()
.id(11L)
.conversationId(CONVERSATION_ID)
.role("user")
.content("message to delete")
.build();
when(messageDao.findByConversationIdOrderByGmtCreateAsc(CONVERSATION_ID))
.thenReturn(List.of(message));
conversationService.deleteConversation(CONVERSATION_ID);
InOrder deletionOrder = inOrder(sopScheduleDao, messageDao, conversationDao);
deletionOrder.verify(sopScheduleDao).deleteByConversationId(CONVERSATION_ID);
deletionOrder.verify(messageDao).deleteAll(List.of(message));
deletionOrder.verify(conversationDao).deleteById(CONVERSATION_ID);
}
}