feat(acceptance): 建立同构验收与弹性容量体系
实现本地三节点 K3s 同构环境、脱敏生产快照、Gemini 图片和多参考图视频协议模拟、统一验收报告及故障注入。\n\n新增 Worker 容量控制器、资源与连接预算、任务恢复保护,并将生产验收拆分为 validation 执行和人工 CAS 放量。\n\n验证包括 Go 全量测试、PostgreSQL HTTP 集成测试、go vet、OpenAPI、ShellCheck、前端检查、迁移及发布脚本测试。
This commit is contained in:
@@ -140,6 +140,57 @@ func TestProcessRolePrecedenceAndCompatibility(t *testing.T) {
|
||||
if !cfg.RunsPublicHTTP() || cfg.RunsAsyncExecutionWorker() || cfg.RunsBackgroundWorkers() {
|
||||
t.Fatalf("api role capabilities are inconsistent: %+v", cfg)
|
||||
}
|
||||
|
||||
t.Setenv("AI_GATEWAY_PROCESS_ROLE", "capacity-controller")
|
||||
cfg = Load()
|
||||
if cfg.RunsPublicHTTP() || cfg.RunsAsyncExecutionWorker() || cfg.RunsBackgroundWorkers() || !cfg.RunsCapacityController() {
|
||||
t.Fatalf("capacity controller role capabilities are inconsistent: %+v", cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkerAutoscalingConfiguration(t *testing.T) {
|
||||
t.Setenv("AI_GATEWAY_WORKER_AUTOSCALING_ENABLED", "true")
|
||||
t.Setenv("AI_GATEWAY_WORKER_REPLICAS_NINGBO", "1")
|
||||
t.Setenv("AI_GATEWAY_WORKER_REPLICAS_HONGKONG", "2")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MIN_REPLICAS_NINGBO", "1")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MIN_REPLICAS_HONGKONG", "1")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MAX_REPLICAS_NINGBO", "2")
|
||||
t.Setenv("AI_GATEWAY_WORKER_MAX_REPLICAS_HONGKONG", "3")
|
||||
cfg := Load()
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Fatalf("valid autoscaling configuration was rejected: %v", err)
|
||||
}
|
||||
if !cfg.WorkerAutoscalingEnabled || cfg.WorkerReplicasHongkong != 2 || cfg.WorkerMaxReplicasHongkong != 3 {
|
||||
t.Fatalf("autoscaling configuration=%+v", cfg)
|
||||
}
|
||||
cfg.WorkerReplicasHongkong = 4
|
||||
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "bootstrap") {
|
||||
t.Fatalf("Validate() error=%v, want bootstrap bound failure", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPrefersWorkerGlobalHardLimitAlias(t *testing.T) {
|
||||
t.Setenv("AI_GATEWAY_ASYNC_WORKER_HARD_LIMIT", "48")
|
||||
t.Setenv("AI_GATEWAY_ASYNC_WORKER_GLOBAL_HARD_LIMIT", "96")
|
||||
cfg := Load()
|
||||
if cfg.AsyncWorkerHardLimit != 96 {
|
||||
t.Fatalf("global worker hard limit=%d, want 96", cfg.AsyncWorkerHardLimit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatePostgresReplicaBudgets(t *testing.T) {
|
||||
cfg := Load()
|
||||
if cfg.PostgresConnectionBudget != 150 || cfg.PostgresNonWorkerConnectionBudget != 72 {
|
||||
t.Fatalf(
|
||||
"PostgreSQL budgets=%d/%d, want 150/72",
|
||||
cfg.PostgresConnectionBudget,
|
||||
cfg.PostgresNonWorkerConnectionBudget,
|
||||
)
|
||||
}
|
||||
cfg.PostgresNonWorkerConnectionBudget = cfg.PostgresConnectionBudget
|
||||
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "NON_WORKER") {
|
||||
t.Fatalf("Validate() error=%v, want non-Worker budget failure", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateProcessRoleAndDatabasePool(t *testing.T) {
|
||||
@@ -171,6 +222,12 @@ func TestValidateProcessRoleAndDatabasePool(t *testing.T) {
|
||||
t.Fatalf("Validate() error = %v, want invalid database min idle conns", err)
|
||||
}
|
||||
cfg.DatabaseMinIdleConns = 4
|
||||
cfg.DatabaseCriticalMaxConns = 4
|
||||
cfg.DatabaseRiverMaxConns = 12
|
||||
if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "River") {
|
||||
t.Fatalf("Validate() error = %v, want database pool budget failure", err)
|
||||
}
|
||||
cfg.DatabaseRiverMaxConns = 4
|
||||
t.Setenv("AI_GATEWAY_DATABASE_MIN_IDLE_CONNS", "not-an-integer")
|
||||
if err := Load().Validate(); err == nil || !strings.Contains(err.Error(), "DATABASE_MIN_IDLE_CONNS") {
|
||||
t.Fatalf("Validate() error = %v, want invalid non-integer database min idle conns", err)
|
||||
|
||||
Reference in New Issue
Block a user