task-170: 紫鸟客户端配置接入(ZiniaoHttpConfigResolver 超时/重试读取,read 模块级现有配置优先、命名空间兜底)+ 8 条测试
- resolver 提供 connect/read/call/maxRetries/baseRetryDelay 访问面,不改动 ZiniaoClientImpl 调用点 - read 优先取 aiimage.ziniao.read-timeout-seconds(生产默认 15s,与 requestFactory(15000) 现状一致),未配置回退 aiimage.http-client.* - 仅新增类与测试,零生产行为变化
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
package com.nanri.aiimage.config;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 紫鸟客户端统一配置解析(task-170)。
|
||||||
|
*
|
||||||
|
* 真实基线(已核实):连接超时来自共享 HttpClient(HttpClientPool connect=10s,
|
||||||
|
* 不读 aiimage.ziniao.connect 字段);读取超时由 ZiniaoClientImpl 取
|
||||||
|
* aiimage.ziniao.read-timeout-seconds*1000(生产默认 15s)经 requestFactory 生效;
|
||||||
|
* 当前无 call timeout / 无重试。
|
||||||
|
*
|
||||||
|
* 语义:read 优先取模块级现有配置(保证接入切点时行为不变),未配置时回退命名空间
|
||||||
|
* aiimage.http-client.*;connect/call/retry 取命名空间(未来由命名空间统一治理)。
|
||||||
|
* 仅提供稳定访问面,不改动 ZiniaoClientImpl 调用点。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ZiniaoHttpConfigResolver {
|
||||||
|
|
||||||
|
private final HttpClientProperties httpClientProperties;
|
||||||
|
private final ZiniaoProperties ziniaoProperties;
|
||||||
|
|
||||||
|
/** 连接超时:共享 HttpClient 决定,命名空间默认 10s 与 HttpClientPool 现状一致。 */
|
||||||
|
public long connectTimeoutMillis() {
|
||||||
|
return httpClientProperties.effectiveConnectTimeoutMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 读取超时:模块级秒数优先(现状 15s);未配置时回退命名空间。 */
|
||||||
|
public long readTimeoutMillis() {
|
||||||
|
int moduleSeconds = ziniaoProperties.getReadTimeoutSeconds();
|
||||||
|
if (moduleSeconds > 0) {
|
||||||
|
return moduleSeconds * 1_000L;
|
||||||
|
}
|
||||||
|
return httpClientProperties.effectiveReadTimeoutMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long callTimeoutMillis() {
|
||||||
|
return httpClientProperties.effectiveCallTimeoutMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int maxRetries() {
|
||||||
|
return httpClientProperties.effectiveMaxRetries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long baseRetryDelayMillis() {
|
||||||
|
return httpClientProperties.getBaseRetryDelayMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.nanri.aiimage.config;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task-170:紫鸟客户端配置接入契约(plan 10,诚实模式)。
|
||||||
|
*
|
||||||
|
* 现网真实基线(已核实):
|
||||||
|
* - 连接超时:共用 HttpClient(HttpClientPool connect=10s),不读 aiimage.ziniao.connect 字段;
|
||||||
|
* - 读取超时:ZiniaoClientImpl 用 ziniaoProperties.readTimeoutSeconds*1000(生产默认 15s);
|
||||||
|
* - 无 call timeout / 无重试。
|
||||||
|
*
|
||||||
|
* resolver 语义:模块级现有配置优先(read 取 aiimage.ziniao 秒数),命名空间兜底;
|
||||||
|
* 不改调用点,保证接入未来切点时行为不变。
|
||||||
|
*/
|
||||||
|
class ZiniaoHttpConfigResolverTest {
|
||||||
|
|
||||||
|
private HttpClientProperties http;
|
||||||
|
private ZiniaoProperties ziniao;
|
||||||
|
private ZiniaoHttpConfigResolver resolver;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
http = new HttpClientProperties();
|
||||||
|
ziniao = new ZiniaoProperties();
|
||||||
|
resolver = new ZiniaoHttpConfigResolver(http, ziniao);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void readDefaultsToCurrentZiniaoModuleConfig() {
|
||||||
|
// 生产现状:aiimage.ziniao.read-timeout-seconds=15 → requestFactory(15000)
|
||||||
|
ziniao.setReadTimeoutSeconds(15);
|
||||||
|
assertEquals(15_000L, resolver.readTimeoutMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void moduleReadWinsOverNamespace() {
|
||||||
|
// 模块级现有配置优先,命名空间覆盖不影响紫鸟 read(行为不变)
|
||||||
|
ziniao.setReadTimeoutSeconds(15);
|
||||||
|
http.setReadTimeoutMillis(120_000);
|
||||||
|
assertEquals(15_000L, resolver.readTimeoutMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void readFallsBackToNamespaceWhenModuleUnset() {
|
||||||
|
// 模块未配置(<=0) → 命名空间 read(默认 60s,可覆盖)
|
||||||
|
ziniao.setReadTimeoutSeconds(0);
|
||||||
|
assertEquals(60_000L, resolver.readTimeoutMillis());
|
||||||
|
http.setReadTimeoutMillis(30_000);
|
||||||
|
assertEquals(30_000L, resolver.readTimeoutMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void connectMatchesSharedClientBaseline() {
|
||||||
|
// 连接超时由共享 HttpClient 决定(HttpClientPool 硬编码 10s),不读模块 connect 字段
|
||||||
|
assertEquals(10_000L, resolver.connectTimeoutMillis());
|
||||||
|
http.setConnectTimeoutMillis(30_000);
|
||||||
|
assertEquals(30_000L, resolver.connectTimeoutMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void callTimeoutFromNamespace() {
|
||||||
|
assertEquals(90_000L, resolver.callTimeoutMillis());
|
||||||
|
http.setCallTimeoutMillis(180_000);
|
||||||
|
assertEquals(180_000L, resolver.callTimeoutMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void retryFromNamespaceClamped() {
|
||||||
|
assertEquals(3, resolver.maxRetries());
|
||||||
|
http.setMaxRetries(99);
|
||||||
|
assertEquals(10, resolver.maxRetries(), "命名空间重试钳制到 10");
|
||||||
|
assertEquals(500L, resolver.baseRetryDelayMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void invalidNamespaceTimeoutsClamped() {
|
||||||
|
http.setConnectTimeoutMillis(-1);
|
||||||
|
assertEquals(1_000L, resolver.connectTimeoutMillis());
|
||||||
|
ziniao.setReadTimeoutSeconds(0);
|
||||||
|
http.setReadTimeoutMillis(999_999_999L);
|
||||||
|
assertEquals(3_600_000L, resolver.readTimeoutMillis(), "命名空间 read 钳制到 3600s");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void resolverWiredAsStableAccessSurface() {
|
||||||
|
// 作为未来 ZiniaoClientImpl 切换读取源时的稳定访问面
|
||||||
|
assertTrue(resolver.connectTimeoutMillis() > 0);
|
||||||
|
assertTrue(resolver.readTimeoutMillis() > 0);
|
||||||
|
assertTrue(resolver.maxRetries() >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user