feat(acceptance): 建立同构验收与弹性容量体系
实现本地三节点 K3s 同构环境、脱敏生产快照、Gemini 图片和多参考图视频协议模拟、统一验收报告及故障注入。\n\n新增 Worker 容量控制器、资源与连接预算、任务恢复保护,并将生产验收拆分为 validation 执行和人工 CAS 放量。\n\n验证包括 Go 全量测试、PostgreSQL HTTP 集成测试、go vet、OpenAPI、ShellCheck、前端检查、迁移及发布脚本测试。
This commit is contained in:
@@ -178,9 +178,45 @@ func (s *Server) logPostgresUnavailable(message string) {
|
||||
"postgres_pool_idle_connections", statistics.IdleConns(),
|
||||
"postgres_pool_empty_acquire_count", statistics.EmptyAcquireCount(),
|
||||
"postgres_pool_canceled_acquire_count", statistics.CanceledAcquireCount(),
|
||||
"postgres_critical_pool", s.criticalPostgresPoolLogFields(),
|
||||
"postgres_river_pool", s.riverPostgresPoolLogFields(),
|
||||
)
|
||||
}
|
||||
|
||||
func (s *Server) criticalPostgresPoolLogFields() map[string]any {
|
||||
if s.coordinationStore == nil || s.coordinationStore == s.store ||
|
||||
s.coordinationStore.Pool() == nil {
|
||||
return map[string]any{"separate": false}
|
||||
}
|
||||
statistics := s.coordinationStore.Pool().Stat()
|
||||
return map[string]any{
|
||||
"separate": true,
|
||||
"max_connections": statistics.MaxConns(),
|
||||
"total_connections": statistics.TotalConns(),
|
||||
"acquired_connections": statistics.AcquiredConns(),
|
||||
"idle_connections": statistics.IdleConns(),
|
||||
"empty_acquire_count": statistics.EmptyAcquireCount(),
|
||||
"canceled_acquire_count": statistics.CanceledAcquireCount(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) riverPostgresPoolLogFields() map[string]any {
|
||||
if s.riverStore == nil || s.riverStore == s.store ||
|
||||
s.riverStore.Pool() == nil {
|
||||
return map[string]any{"separate": false}
|
||||
}
|
||||
statistics := s.riverStore.Pool().Stat()
|
||||
return map[string]any{
|
||||
"separate": true,
|
||||
"max_connections": statistics.MaxConns(),
|
||||
"total_connections": statistics.TotalConns(),
|
||||
"acquired_connections": statistics.AcquiredConns(),
|
||||
"idle_connections": statistics.IdleConns(),
|
||||
"empty_acquire_count": statistics.EmptyAcquireCount(),
|
||||
"canceled_acquire_count": statistics.CanceledAcquireCount(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) localIdentityEnabled() bool {
|
||||
mode := strings.ToLower(strings.TrimSpace(s.cfg.IdentityMode))
|
||||
return mode == "" || mode == "standalone" || mode == "hybrid"
|
||||
@@ -1183,6 +1219,11 @@ func (s *Server) createTask(kind string, compatible bool) http.Handler {
|
||||
}
|
||||
created, err := s.store.CreateTaskIdempotent(r.Context(), createInput, user)
|
||||
if err != nil {
|
||||
if errors.Is(err, store.ErrRateLimited) {
|
||||
applyRunErrorHeaders(w, err)
|
||||
writeTaskError(statusFromRunError(err), runErrorMessage(err), runErrorDetails(err), runErrorCode(err))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, store.ErrIdempotencyKeyReused) {
|
||||
writeTaskError(http.StatusConflict, "Idempotency-Key was reused for a different request", nil, "idempotency_key_reused")
|
||||
return
|
||||
@@ -1200,8 +1241,9 @@ func (s *Server) createTask(kind string, compatible bool) http.Handler {
|
||||
if s.billingMetrics != nil {
|
||||
s.billingMetrics.ObserveBillingEvent("idempotent_replay")
|
||||
}
|
||||
if targetProtocol == "" {
|
||||
if targetProtocol == "" || gatewayAPIV1Request(r) {
|
||||
w.Header().Set("Idempotent-Replayed", "true")
|
||||
w.Header().Set("X-Gateway-Task-Id", task.ID)
|
||||
}
|
||||
if responsePlan.streamMode {
|
||||
writeTaskError(http.StatusConflict, "streaming idempotent replay is not supported", nil, "idempotency_stream_replay_unsupported")
|
||||
@@ -1411,7 +1453,7 @@ func writeCompatibleTaskResponse(runCtx context.Context, w http.ResponseWriter,
|
||||
}
|
||||
|
||||
func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.ResponseWriter, r *http.Request, executor taskExecutor, kind string, model string, targetProtocol string, task store.GatewayTask, user *auth.User, streamMode bool, includeUsage bool) {
|
||||
if targetProtocol == "" {
|
||||
if targetProtocol == "" || gatewayAPIV1Request(r) {
|
||||
w.Header().Set("X-Gateway-Task-Id", task.ID)
|
||||
}
|
||||
if streamMode {
|
||||
@@ -1515,6 +1557,10 @@ func writeProtocolCompatibleTaskResponse(runCtx context.Context, w http.Response
|
||||
writeJSON(w, http.StatusOK, easyAISynchronousTaskResponse(result.Task, result.Output))
|
||||
}
|
||||
|
||||
func gatewayAPIV1Request(r *http.Request) bool {
|
||||
return r != nil && strings.HasPrefix(r.URL.Path, "/api/v1/")
|
||||
}
|
||||
|
||||
func streamIncludeUsage(body map[string]any) bool {
|
||||
streamOptions, _ := body["stream_options"].(map[string]any)
|
||||
includeUsage, _ := streamOptions["include_usage"].(bool)
|
||||
|
||||
Reference in New Issue
Block a user