Persist failed AI generation records
This commit is contained in:
@@ -19,7 +19,6 @@ import com.ruoyi.generator.domain.front.dto.DatabaseDesignResponse;
|
||||
import com.ruoyi.generator.domain.front.dto.DatabaseTableDesign;
|
||||
import com.ruoyi.generator.domain.front.dto.GenerateDatabaseRequest;
|
||||
import com.ruoyi.generator.mapper.front.FrontProjectColumnMapper;
|
||||
import com.ruoyi.generator.mapper.front.FrontProjectGenerationMapper;
|
||||
import com.ruoyi.generator.mapper.front.FrontProjectMapper;
|
||||
import com.ruoyi.generator.mapper.front.FrontProjectTableMapper;
|
||||
|
||||
@@ -41,7 +40,7 @@ public class AiGenerateServiceImpl implements IAiGenerateService
|
||||
@Autowired
|
||||
private FrontProjectColumnMapper frontProjectColumnMapper;
|
||||
@Autowired
|
||||
private FrontProjectGenerationMapper frontProjectGenerationMapper;
|
||||
private AiGenerationRecordService generationRecordService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@@ -63,7 +62,7 @@ public class AiGenerateServiceImpl implements IAiGenerateService
|
||||
generation.setResponsePayload(aiContent);
|
||||
generation.setSuccess("1");
|
||||
generation.setElapsedMs(System.currentTimeMillis() - start);
|
||||
frontProjectGenerationMapper.insertFrontProjectGeneration(generation);
|
||||
generationRecordService.insert(generation);
|
||||
return response;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
@@ -71,7 +70,7 @@ public class AiGenerateServiceImpl implements IAiGenerateService
|
||||
generation.setSuccess("0");
|
||||
generation.setErrorMessage(e.getMessage());
|
||||
generation.setElapsedMs(System.currentTimeMillis() - start);
|
||||
frontProjectGenerationMapper.insertFrontProjectGeneration(generation);
|
||||
generationRecordService.insert(generation);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruoyi.generator.service.front;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.ruoyi.generator.domain.front.FrontProjectGeneration;
|
||||
import com.ruoyi.generator.mapper.front.FrontProjectGenerationMapper;
|
||||
|
||||
@Service
|
||||
public class AiGenerationRecordService
|
||||
{
|
||||
@Autowired
|
||||
private FrontProjectGenerationMapper frontProjectGenerationMapper;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void insert(FrontProjectGeneration generation)
|
||||
{
|
||||
frontProjectGenerationMapper.insertFrontProjectGeneration(generation);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,25 @@
|
||||
package com.ruoyi.generator.service.front;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.ruoyi.generator.config.DeepSeekProperties;
|
||||
import com.ruoyi.generator.domain.front.FrontProject;
|
||||
import com.ruoyi.generator.domain.front.FrontProjectColumn;
|
||||
@@ -38,17 +46,20 @@ public class AiGenerateServiceImplTest
|
||||
private FrontProjectColumnMapper frontProjectColumnMapper;
|
||||
@Mock
|
||||
private FrontProjectGenerationMapper frontProjectGenerationMapper;
|
||||
private AiGenerationRecordService generationRecordService;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
MockitoAnnotations.initMocks(this);
|
||||
service = new AiGenerateServiceImpl();
|
||||
generationRecordService = new AiGenerationRecordService();
|
||||
setField(generationRecordService, "frontProjectGenerationMapper", frontProjectGenerationMapper);
|
||||
setField("deepSeekClient", deepSeekClient);
|
||||
setField("frontProjectMapper", frontProjectMapper);
|
||||
setField("frontProjectTableMapper", frontProjectTableMapper);
|
||||
setField("frontProjectColumnMapper", frontProjectColumnMapper);
|
||||
setField("frontProjectGenerationMapper", frontProjectGenerationMapper);
|
||||
setField("generationRecordService", generationRecordService);
|
||||
setField("validator", new AiDatabaseSchemaValidator());
|
||||
setField("ddlBuilder", new MysqlDdlBuilder());
|
||||
setField("deepSeekProperties", new DeepSeekProperties());
|
||||
@@ -76,11 +87,51 @@ public class AiGenerateServiceImplTest
|
||||
assertTrue(response.getSql().contains("CREATE TABLE `car_info`"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateDatabasePersistsFailureGenerationRecordBeforePropagatingClientFailure()
|
||||
{
|
||||
RuntimeException failure = new RuntimeException("DeepSeek unavailable");
|
||||
when(frontProjectMapper.selectFrontProjectByUserAndId(7L, 10L)).thenReturn(project());
|
||||
when(deepSeekClient.chat(anyString())).thenThrow(failure);
|
||||
|
||||
try
|
||||
{
|
||||
service.generateDatabase(7L, 10L, request());
|
||||
fail("Expected client failure");
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
assertSame(failure, e);
|
||||
}
|
||||
|
||||
ArgumentCaptor<FrontProjectGeneration> generationCaptor = ArgumentCaptor.forClass(FrontProjectGeneration.class);
|
||||
verify(frontProjectGenerationMapper).insertFrontProjectGeneration(generationCaptor.capture());
|
||||
assertEquals("0", generationCaptor.getValue().getSuccess());
|
||||
assertEquals("DeepSeek unavailable", generationCaptor.getValue().getErrorMessage());
|
||||
verify(frontProjectColumnMapper, never()).deleteColumnsByProjectId(10L);
|
||||
verify(frontProjectTableMapper, never()).deleteTablesByProjectId(10L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generationRecordInsertUsesRequiresNewTransaction() throws Exception
|
||||
{
|
||||
Method method = AiGenerationRecordService.class.getDeclaredMethod("insert", FrontProjectGeneration.class);
|
||||
Transactional transactional = method.getAnnotation(Transactional.class);
|
||||
|
||||
assertNotNull(transactional);
|
||||
assertEquals(Propagation.REQUIRES_NEW, transactional.propagation());
|
||||
}
|
||||
|
||||
private void setField(String name, Object value) throws Exception
|
||||
{
|
||||
Field field = AiGenerateServiceImpl.class.getDeclaredField(name);
|
||||
setField(service, name, value);
|
||||
}
|
||||
|
||||
private void setField(Object target, String name, Object value) throws Exception
|
||||
{
|
||||
Field field = target.getClass().getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
field.set(service, value);
|
||||
field.set(target, value);
|
||||
}
|
||||
|
||||
private FrontProject project()
|
||||
|
||||
Reference in New Issue
Block a user