Commit 78976885fd5b86de869db65c7a1acba8ec59376d
1 parent
edffc819
fix(ai1): 对齐消息页顺序并兼容 JDK 17
Showing
6 changed files
with
31 additions
and
12 deletions
yudao-module-ai1-springai/src/main/java/cn/iocoder/yudao/module/ai1/controller/admin/session/Ai1SessionMessageController.java
| @@ -77,7 +77,7 @@ public class Ai1SessionMessageController { | @@ -77,7 +77,7 @@ public class Ai1SessionMessageController { | ||
| 77 | // ==================== 管理 ==================== | 77 | // ==================== 管理 ==================== |
| 78 | 78 | ||
| 79 | @GetMapping("/page") | 79 | @GetMapping("/page") |
| 80 | - @Operation(summary = "获得会话消息分页", description = "按消息编号倒序") | 80 | + @Operation(summary = "获得会话消息分页", description = "按消息编号倒序取最新页,页内按时间正序") |
| 81 | @PreAuthorize("@ss.hasPermission('ai1:session:query')") | 81 | @PreAuthorize("@ss.hasPermission('ai1:session:query')") |
| 82 | public CommonResult<PageResult<Ai1SessionMessageRespVO>> getSessionMessagePage(@Valid Ai1SessionMessagePageReqVO pageReqVO) { | 82 | public CommonResult<PageResult<Ai1SessionMessageRespVO>> getSessionMessagePage(@Valid Ai1SessionMessagePageReqVO pageReqVO) { |
| 83 | return success(BeanUtils.toBean(sessionMessageService.getSessionMessagePage(pageReqVO), | 83 | return success(BeanUtils.toBean(sessionMessageService.getSessionMessagePage(pageReqVO), |
yudao-module-ai1-springai/src/main/java/cn/iocoder/yudao/module/ai1/harness/session/Ai1SessionStreamTool.java
| @@ -529,7 +529,7 @@ public class Ai1SessionStreamTool implements SmartLifecycle { | @@ -529,7 +529,7 @@ public class Ai1SessionStreamTool implements SmartLifecycle { | ||
| 529 | if (!lock.tryLock()) { | 529 | if (!lock.tryLock()) { |
| 530 | return false; | 530 | return false; |
| 531 | } | 531 | } |
| 532 | - long ownerThreadId = Thread.currentThread().threadId(); | 532 | + long ownerThreadId = Thread.currentThread().getId(); |
| 533 | try { | 533 | try { |
| 534 | // 3. 锁内重新读取,期间可能已被 worker 完成 | 534 | // 3. 锁内重新读取,期间可能已被 worker 完成 |
| 535 | Ai1SessionMessageDO current = sessionMessageService.getSessionMessage(messageId); | 535 | Ai1SessionMessageDO current = sessionMessageService.getSessionMessage(messageId); |
| @@ -687,7 +687,7 @@ public class Ai1SessionStreamTool implements SmartLifecycle { | @@ -687,7 +687,7 @@ public class Ai1SessionStreamTool implements SmartLifecycle { | ||
| 687 | if (!lock.tryLock()) { | 687 | if (!lock.tryLock()) { |
| 688 | return; | 688 | return; |
| 689 | } | 689 | } |
| 690 | - long workerThreadId = Thread.currentThread().threadId(); | 690 | + long workerThreadId = Thread.currentThread().getId(); |
| 691 | try { | 691 | try { |
| 692 | Long tenantId = Convert.toLong(fields.get(FIELD_TENANT_ID)); | 692 | Long tenantId = Convert.toLong(fields.get(FIELD_TENANT_ID)); |
| 693 | TenantUtils.execute(tenantId, () -> executeTask(recordId, fields, messageId, lock, workerThreadId, reclaimed)); | 693 | TenantUtils.execute(tenantId, () -> executeTask(recordId, fields, messageId, lock, workerThreadId, reclaimed)); |
yudao-module-ai1-springai/src/main/java/cn/iocoder/yudao/module/ai1/service/session/Ai1SessionMessageService.java
| @@ -26,7 +26,7 @@ public interface Ai1SessionMessageService { | @@ -26,7 +26,7 @@ public interface Ai1SessionMessageService { | ||
| 26 | List<Ai1SessionMessageDO> getSessionMessageListBySessionId(Long sessionId); | 26 | List<Ai1SessionMessageDO> getSessionMessageListBySessionId(Long sessionId); |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| 29 | - * 获得会话消息分页,按编号倒序 | 29 | + * 获得会话消息分页,按编号倒序取最新页,页内按时间正序 |
| 30 | * | 30 | * |
| 31 | * @param pageReqVO 分页查询 | 31 | * @param pageReqVO 分页查询 |
| 32 | * @return 消息分页 | 32 | * @return 消息分页 |
yudao-module-ai1-springai/src/main/java/cn/iocoder/yudao/module/ai1/service/session/Ai1SessionMessageServiceImpl.java
| @@ -63,7 +63,12 @@ public class Ai1SessionMessageServiceImpl implements Ai1SessionMessageService { | @@ -63,7 +63,12 @@ public class Ai1SessionMessageServiceImpl implements Ai1SessionMessageService { | ||
| 63 | 63 | ||
| 64 | @Override | 64 | @Override |
| 65 | public PageResult<Ai1SessionMessageDO> getSessionMessagePage(Ai1SessionMessagePageReqVO pageReqVO) { | 65 | public PageResult<Ai1SessionMessageDO> getSessionMessagePage(Ai1SessionMessagePageReqVO pageReqVO) { |
| 66 | - return sessionMessageMapper.selectPage(pageReqVO); | 66 | + PageResult<Ai1SessionMessageDO> pageResult = sessionMessageMapper.selectPage(pageReqVO); |
| 67 | + // 按编号倒序取最新页,页内反转为时间正序 | ||
| 68 | + if (CollUtil.isNotEmpty(pageResult.getList())) { | ||
| 69 | + Collections.reverse(pageResult.getList()); | ||
| 70 | + } | ||
| 71 | + return pageResult; | ||
| 67 | } | 72 | } |
| 68 | 73 | ||
| 69 | @Override | 74 | @Override |
yudao-module-ai1-springai/src/test/java/cn/iocoder/yudao/module/ai1/harness/mcp/Ai1McpToolFactoryTest.java
| @@ -67,7 +67,7 @@ public class Ai1McpToolFactoryTest extends BaseMockitoUnitTest { | @@ -67,7 +67,7 @@ public class Ai1McpToolFactoryTest extends BaseMockitoUnitTest { | ||
| 67 | // 调用 | 67 | // 调用 |
| 68 | List<ToolCallback> callbacks = buildTools(List.of(mcp), List.of("search")); | 68 | List<ToolCallback> callbacks = buildTools(List.of(mcp), List.of("search")); |
| 69 | // 断言 | 69 | // 断言 |
| 70 | - assertEquals("github__search", callbacks.getFirst().getToolDefinition().name()); | 70 | + assertEquals("github__search", callbacks.get(0).getToolDefinition().name()); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | @Test | 73 | @Test |
| @@ -78,8 +78,8 @@ public class Ai1McpToolFactoryTest extends BaseMockitoUnitTest { | @@ -78,8 +78,8 @@ public class Ai1McpToolFactoryTest extends BaseMockitoUnitTest { | ||
| 78 | // 调用 | 78 | // 调用 |
| 79 | List<ToolCallback> callbacks = buildTools(List.of(mcp), List.of("search")); | 79 | List<ToolCallback> callbacks = buildTools(List.of(mcp), List.of("search")); |
| 80 | // 断言 | 80 | // 断言 |
| 81 | - assertEquals("a".repeat(56) + "__search", callbacks.getFirst().getToolDefinition().name()); | ||
| 82 | - assertEquals(64, callbacks.getFirst().getToolDefinition().name().length()); | 81 | + assertEquals("a".repeat(56) + "__search", callbacks.get(0).getToolDefinition().name()); |
| 82 | + assertEquals(64, callbacks.get(0).getToolDefinition().name().length()); | ||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | @Test | 85 | @Test |
| @@ -127,7 +127,7 @@ public class Ai1McpToolFactoryTest extends BaseMockitoUnitTest { | @@ -127,7 +127,7 @@ public class Ai1McpToolFactoryTest extends BaseMockitoUnitTest { | ||
| 127 | List<ToolCallback> callbacks = buildTools(List.of(mcp), List.of(toolName)); | 127 | List<ToolCallback> callbacks = buildTools(List.of(mcp), List.of(toolName)); |
| 128 | 128 | ||
| 129 | // 调用 | 129 | // 调用 |
| 130 | - String result = callbacks.getFirst().call("{\"query\":\"北京\"}"); | 130 | + String result = callbacks.get(0).call("{\"query\":\"北京\"}"); |
| 131 | // 断言 | 131 | // 断言 |
| 132 | assertEquals("搜索结果", JsonUtils.parseObject(result, String.class)); | 132 | assertEquals("搜索结果", JsonUtils.parseObject(result, String.class)); |
| 133 | verify(mcpClientTool).callTool(mcp, toolName, arguments); | 133 | verify(mcpClientTool).callTool(mcp, toolName, arguments); |
yudao-module-ai1-springai/src/test/java/cn/iocoder/yudao/module/ai1/service/session/Ai1SessionMessageServiceImplTest.java
| @@ -171,11 +171,25 @@ public class Ai1SessionMessageServiceImplTest extends BaseDbUnitTest { | @@ -171,11 +171,25 @@ public class Ai1SessionMessageServiceImplTest extends BaseDbUnitTest { | ||
| 171 | 171 | ||
| 172 | // 调用 | 172 | // 调用 |
| 173 | PageResult<Ai1SessionMessageDO> pageResult = sessionMessageService.getSessionMessagePage(reqVO); | 173 | PageResult<Ai1SessionMessageDO> pageResult = sessionMessageService.getSessionMessagePage(reqVO); |
| 174 | - // 断言:按编号倒序 | 174 | + // 断言:取最新一页,页内按时间正序 |
| 175 | assertEquals(3, pageResult.getTotal()); | 175 | assertEquals(3, pageResult.getTotal()); |
| 176 | - assertEquals(List.of(message3.getId(), message2.getId()), | 176 | + assertEquals(List.of(message2.getId(), message3.getId()), |
| 177 | pageResult.getList().stream().map(Ai1SessionMessageDO::getId).toList()); | 177 | pageResult.getList().stream().map(Ai1SessionMessageDO::getId).toList()); |
| 178 | - assertNotEquals(message1.getId(), pageResult.getList().get(1).getId()); | 178 | + |
| 179 | + // 调用:第二页 | ||
| 180 | + reqVO.setPageNo(2); | ||
| 181 | + pageResult = sessionMessageService.getSessionMessagePage(reqVO); | ||
| 182 | + // 断言:更早的消息 | ||
| 183 | + assertEquals(3, pageResult.getTotal()); | ||
| 184 | + assertEquals(List.of(message1.getId()), | ||
| 185 | + pageResult.getList().stream().map(Ai1SessionMessageDO::getId).toList()); | ||
| 186 | + | ||
| 187 | + // 调用:超出范围的空页 | ||
| 188 | + reqVO.setPageNo(3); | ||
| 189 | + pageResult = sessionMessageService.getSessionMessagePage(reqVO); | ||
| 190 | + // 断言 | ||
| 191 | + assertEquals(3, pageResult.getTotal()); | ||
| 192 | + assertTrue(pageResult.getList().isEmpty()); | ||
| 179 | } | 193 | } |
| 180 | 194 | ||
| 181 | @Test | 195 | @Test |