feat: update task routing and coze handling
This commit is contained in:
+86
@@ -0,0 +1,86 @@
|
||||
package com.nanri.aiimage.modules.similarasin.client;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.nanri.aiimage.config.SimilarAsinProperties;
|
||||
import com.nanri.aiimage.modules.similarasin.model.dto.SimilarAsinResultRowDto;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class SimilarAsinCozeClientTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void buildParametersIncludesAlibabaPriceFromPythonPayload() throws Exception {
|
||||
List<SimilarAsinResultRowDto> rows = objectMapper.readValue("""
|
||||
[
|
||||
{
|
||||
"asin": "B0TEST123",
|
||||
"url": "https://m.media-amazon.com/images/I/main.jpg",
|
||||
"alibaba": [
|
||||
{"url": "https://cbu01.alicdn.com/img/ibank/a.jpg", "price": 12.80},
|
||||
{"url": "https://cbu01.alicdn.com/img/ibank/b.jpg", "price": 19.99}
|
||||
],
|
||||
"title": "Test title",
|
||||
"sku": "SKU-1"
|
||||
}
|
||||
]
|
||||
""", new TypeReference<>() {
|
||||
});
|
||||
SimilarAsinCozeClient client = new SimilarAsinCozeClient(new SimilarAsinProperties(), objectMapper, null);
|
||||
|
||||
Method method = SimilarAsinCozeClient.class.getDeclaredMethod(
|
||||
"buildParameters", List.class, String.class, String.class, boolean.class);
|
||||
method.setAccessible(true);
|
||||
Map<String, Object> parameters = (Map<String, Object>) method.invoke(client, rows, "", "", true);
|
||||
|
||||
List<Map<String, Object>> items = (List<Map<String, Object>>) parameters.get("items");
|
||||
Map<String, Object> item = items.getFirst();
|
||||
List<Map<String, Object>> alibaba = (List<Map<String, Object>>) item.get("alibaba");
|
||||
|
||||
assertEquals("B0TEST123", item.get("asin"));
|
||||
assertEquals("https://m.media-amazon.com/images/I/main.jpg", item.get("url"));
|
||||
assertEquals("Test title", item.get("title"));
|
||||
assertEquals("SKU-1", item.get("sku"));
|
||||
assertEquals(2, alibaba.size());
|
||||
assertEquals("https://cbu01.alicdn.com/img/ibank/a.jpg", alibaba.get(0).get("url"));
|
||||
assertEquals(0, new BigDecimal("12.8").compareTo((BigDecimal) alibaba.get(0).get("price")));
|
||||
assertEquals("https://cbu01.alicdn.com/img/ibank/b.jpg", alibaba.get(1).get("url"));
|
||||
assertEquals(0, new BigDecimal("19.99").compareTo((BigDecimal) alibaba.get(1).get("price")));
|
||||
assertTrue(rows.getFirst().hasImageUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void buildParametersFallsBackAlibabaFromLegacyUrlsAndTopLevelPrice() throws Exception {
|
||||
SimilarAsinResultRowDto row = new SimilarAsinResultRowDto();
|
||||
row.setAsin("B0LEGACY1");
|
||||
row.setUrl("https://m.media-amazon.com/images/I/main.jpg");
|
||||
row.setUrls(List.of("https://cbu01.alicdn.com/img/ibank/legacy-a.jpg"));
|
||||
row.setPrice("8.50");
|
||||
row.setTitle("Legacy title");
|
||||
row.setSku("SKU-LEGACY");
|
||||
SimilarAsinCozeClient client = new SimilarAsinCozeClient(new SimilarAsinProperties(), objectMapper, null);
|
||||
|
||||
Method method = SimilarAsinCozeClient.class.getDeclaredMethod(
|
||||
"buildParameters", List.class, String.class, String.class, boolean.class);
|
||||
method.setAccessible(true);
|
||||
Map<String, Object> parameters = (Map<String, Object>) method.invoke(client, List.of(row), "", "", false);
|
||||
|
||||
List<Map<String, Object>> items = (List<Map<String, Object>>) parameters.get("items");
|
||||
List<Map<String, Object>> alibaba = (List<Map<String, Object>>) items.getFirst().get("alibaba");
|
||||
|
||||
assertEquals(1, alibaba.size());
|
||||
assertEquals("https://cbu01.alicdn.com/img/ibank/legacy-a.jpg", alibaba.getFirst().get("url"));
|
||||
assertEquals(0, new BigDecimal("8.5").compareTo((BigDecimal) alibaba.getFirst().get("price")));
|
||||
}
|
||||
}
|
||||
+46
@@ -7,13 +7,16 @@ import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -154,4 +157,47 @@ class SimilarAsinImageEmbedderTest {
|
||||
assertEquals(12345678L, ex.size());
|
||||
assertTrue(ex.getMessage().contains("oversize"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpClientKeepsImageDownloadResilienceEnabled() {
|
||||
assertTrue(embedder.httpClient().retryOnConnectionFailure(), "OkHttp should retry transient connection failures");
|
||||
assertTrue(embedder.httpClient().followRedirects(), "image CDN redirects should be followed");
|
||||
assertTrue(embedder.httpClient().followSslRedirects(), "signed CDN downloads should follow browser-like SSL redirects");
|
||||
}
|
||||
|
||||
@Test
|
||||
void buildImageRequestUsesBrowserLikeHeaders() {
|
||||
var req = SimilarAsinImageEmbedder.buildImageRequest("https://m.media-amazon.com/images/I/abc.jpg");
|
||||
|
||||
assertEquals("GET", req.method());
|
||||
assertTrue(req.header("User-Agent").contains("Chrome"), "User-Agent should look browser-like");
|
||||
assertTrue(req.header("Accept").contains("image/"), "Accept should prefer images");
|
||||
assertEquals("https://www.amazon.com/", req.header("Referer"));
|
||||
assertEquals("no-cache", req.header("Cache-Control"));
|
||||
assertNotNull(req.header("Accept-Language"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void buildImageRequestUsesDownloadHeadersForCozeSignedImages() {
|
||||
var req = SimilarAsinImageEmbedder.buildImageRequest(
|
||||
"https://lf9-bot-platform-tos-sign.coze.cn/bot-studio-bot-platform/bot_files/1/image/jpeg/2/merged_image.jpg?x-expires=1&x-signature=a");
|
||||
|
||||
assertEquals("GET", req.method());
|
||||
assertTrue(req.header("User-Agent").contains("Chrome"), "User-Agent should look browser-like");
|
||||
assertEquals("*/*", req.header("Accept"));
|
||||
assertNull(req.header("Referer"), "Coze signed download links should not carry an Amazon referer");
|
||||
assertEquals("no-cache", req.header("Cache-Control"));
|
||||
assertTrue(SimilarAsinImageEmbedder.isCozeSignedImageUrl(req.url().toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorSummaryDoesNotHideEmptyTimeoutMessage() {
|
||||
TimeoutException timeout = new TimeoutException();
|
||||
assertEquals("TimeoutException: <empty>", SimilarAsinImageEmbedder.errorSummary(timeout));
|
||||
|
||||
IOException io = new IOException("outer", new TimeoutException("inner"));
|
||||
String summary = SimilarAsinImageEmbedder.errorSummary(io);
|
||||
assertTrue(summary.contains("IOException: outer"));
|
||||
assertTrue(summary.contains("cause=TimeoutException: inner"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user