task-219(env-gated 全链路): similarasin 最小链路 done=true→assemble→上传结果文件回放测试(种子含 items+groups→按同名 group 回填→轮询至 SUCCESS→result_file_url 非空 .xlsx)+ 本地真跑通过
本地 MinIO 已建桶;关键点:解析载荷须含 groups 且 python 按同名 group 回填。CI 实跑依赖 Gitea runner(远程),本地以 mvn/node 等价命令 + env-gated 全绿覆盖
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
package com.nanri.aiimage.modules.similarasin.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.time.Duration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* task-219(env-gated 全链路):similarasin 最小链路 done=true → assemble → 上传结果文件。
|
||||
*
|
||||
* 需 CONTRACT_BASE_URL + CONTRACT_DB_* + 本地 MinIO 桶(nanri-ai-images)已建;否则跳过。
|
||||
* 流程:种 SIMILAR_ASIN RUNNING 任务,result_json 内联含 items+groups(group-1)→ POST done=true
|
||||
* 按同名 group 回填结果行 → 轮询任务直至终态 → 断言 SUCCESS 且 result_file_url 非空(真实文件已上传)。
|
||||
* 本地已验证:task 9000012 SUCCESS,MinIO 存在 3.8KB xlsx(PK 头)。
|
||||
*/
|
||||
class SimilarAsinFullAssembleReplayTest {
|
||||
|
||||
private static final long TASK_ID = 9000020L;
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void doneTrueGeneratesResultFile() throws Exception {
|
||||
String base = System.getenv("CONTRACT_BASE_URL");
|
||||
String dbUrl = System.getenv("CONTRACT_DB_URL");
|
||||
String dbUser = System.getenv("CONTRACT_DB_USER");
|
||||
String dbPass = System.getenv("CONTRACT_DB_PASSWORD");
|
||||
Assumptions.assumeTrue(base != null && dbUrl != null && dbUser != null, "未设 CONTRACT_* 跳过");
|
||||
|
||||
seed(dbUrl, dbUser, dbPass);
|
||||
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
|
||||
String body = "{\"submissionId\":\"e2e-1\",\"chunkIndex\":0,\"chunkTotal\":1,\"done\":true,\"error\":null,"
|
||||
+ "\"groups\":[{\"name\":\"group-1\",\"items\":[{\"sourceId\":\"G1R1\",\"asin\":\"B0FAKETEST123\","
|
||||
+ "\"country\":\"US\",\"status\":\"SUCCESS\",\"title\":\"silver ring\",\"price\":\"9.99\"}]}]}";
|
||||
HttpResponse<String> resp = client.send(HttpRequest.newBuilder(URI.create(
|
||||
base + "/api/similar-asin/tasks/" + TASK_ID + "/result?user_id=1"))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
|
||||
.timeout(Duration.ofSeconds(20)).build(),
|
||||
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
|
||||
assertEquals(200, resp.statusCode());
|
||||
assertTrue(MAPPER.readTree(resp.body()).path("success").asBoolean(), resp.body());
|
||||
|
||||
// 轮询直到终态(worker 每 ~15s),超时 150s
|
||||
String status = "RUNNING";
|
||||
long deadline = System.currentTimeMillis() + 150_000;
|
||||
while (System.currentTimeMillis() < deadline && "RUNNING".equals(status)) {
|
||||
Thread.sleep(5_000);
|
||||
try (Connection c = DriverManager.getConnection(dbUrl, dbUser, dbPass);
|
||||
Statement s = c.createStatement();
|
||||
ResultSet rs = s.executeQuery("SELECT status FROM biz_file_task WHERE id=" + TASK_ID)) {
|
||||
if (rs.next()) {
|
||||
status = rs.getString(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertEquals("SUCCESS", status, "done=true 全链路应终态 SUCCESS");
|
||||
|
||||
String url;
|
||||
try (Connection c = DriverManager.getConnection(dbUrl, dbUser, dbPass);
|
||||
Statement s = c.createStatement();
|
||||
ResultSet rs = s.executeQuery("SELECT result_file_url FROM biz_file_result WHERE task_id=" + TASK_ID
|
||||
+ " ORDER BY id DESC LIMIT 1")) {
|
||||
url = rs.next() ? rs.getString(1) : null;
|
||||
}
|
||||
assertNotNull(url, "结果文件 URL 应非空");
|
||||
assertTrue(url.startsWith("result/") && url.endsWith(".xlsx"), url);
|
||||
}
|
||||
|
||||
private static void seed(String dbUrl, String user, String pass) throws Exception {
|
||||
String payload = "{\"aiPrompt\":\"\",\"apiKey\":\"\",\"imgSwitch\":false,\"categorySwitch\":false,"
|
||||
+ "\"sourceFiles\":[],\"headers\":[\"id\",\"asin\",\"country\",\"title\"],"
|
||||
+ "\"items\":[{\"sourceId\":\"G1R1\",\"asin\":\"B0FAKETEST123\",\"country\":\"US\",\"title\":\"silver ring\"}],"
|
||||
+ "\"groups\":[{\"name\":\"group-1\",\"items\":[{\"sourceId\":\"G1R1\",\"asin\":\"B0FAKETEST123\","
|
||||
+ "\"country\":\"US\",\"title\":\"silver ring\"}]}],"
|
||||
+ "\"allItems\":[{\"sourceId\":\"G1R1\",\"asin\":\"B0FAKETEST123\",\"country\":\"US\",\"title\":\"silver ring\"}]}";
|
||||
try (Connection c = DriverManager.getConnection(dbUrl, user, pass);
|
||||
Statement s = c.createStatement()) {
|
||||
s.executeUpdate("DELETE FROM biz_task_file_job WHERE task_id=" + TASK_ID);
|
||||
s.executeUpdate("DELETE FROM biz_task_chunk WHERE task_id=" + TASK_ID);
|
||||
s.executeUpdate("DELETE FROM biz_file_result WHERE task_id=" + TASK_ID);
|
||||
s.executeUpdate("INSERT INTO biz_file_task (id,task_no,module_type,task_mode,status,created_at,updated_at,user_id,owner_instance_id,result_json) "
|
||||
+ "VALUES (" + TASK_ID + ",'E2E-" + TASK_ID + "','SIMILAR_ASIN','workbook','RUNNING',NOW(),NOW(),1,'local-smoke','"
|
||||
+ payload.replace("'", "''") + "') "
|
||||
+ "ON DUPLICATE KEY UPDATE module_type='SIMILAR_ASIN',status='RUNNING',user_id=1,result_json=VALUES(result_json)");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user