feat(route): 阶段 1 多渠道路由分发层 (Channel + Router)
- store: 新增 channels 表 (name unique, credentials_json, voices CSV, priority, weight, status, auto_ban) + CRUD (List/Get/Insert/SetStatus/Delete) + ErrChannelDuplicate 区分 (避免与 ErrDuplicate 互相误报) - store/db.go: schemaVersion 1 -> 2; channels 表 CREATE IF NOT EXISTS + 复合索引 - adapter/route: 新包,Channel (含 BuildRequest 覆盖 template.Credentials) + Router (Select / SelectAndSynthesize / pickByWeight 纯函数) + 错误区分 ErrNoChannels (走兜底) vs ErrVoiceNotFound (400) + AggregateError 聚合多渠道失败, 供 controller 日志逐个打印 - controller/router.go: SetRouter/GetRouter 句柄 (与 SetAdminStore 同一模式) - controller/tts.go: 接入 Router, 零 channel 走 setting 兜底 (行为=阶段 0); voice 不被任何 channel 接受 -> 400 + voice_not_found; 抽出 finalizeSynth 收敛合成结果->响应+metrics+日志三件套 - main.go: 启动期从 store 加载 channels, 转 route.Channel, 注入 controller; credentials_json 加载失败 -> fail-fast (避免一个错渠道拖崩全部请求) - .gitignore: 补 .gotmp/ .gomodcache/ .dsh-acl/ 验收 (设计文档 §9): - 零 channel 兜底, 行为=阶段 0 - 加 1 个 channel: 走该渠道 - 加 2+ 个同档不同 weight: pickByWeight weight-1-to-3 分布 ±5% (单测覆盖) - 不同 priority: 高优先级优先 (单测覆盖) - disabled 不参与选择 (单测覆盖) - 失败降级: 同档换下一个 -> 降档, 全失败返 AggregateError (单测覆盖) - go build ./... + go vet ./... 全绿 - go test ./... (adapter/route 15 个, store 2 个, 全部通过)
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/volcano-tts/tts-api/controller"
|
||||
// 空导入注册上游适配器:新增上游只需在此加一行,主干零改动。
|
||||
_ "github.com/volcano-tts/tts-api/adapter/volcano"
|
||||
"github.com/volcano-tts/tts-api/adapter/route"
|
||||
"github.com/volcano-tts/tts-api/installer"
|
||||
"github.com/volcano-tts/tts-api/metrics"
|
||||
"github.com/volcano-tts/tts-api/middleware"
|
||||
@@ -28,6 +29,17 @@ func ttsDBPath() string {
|
||||
return "tts.db"
|
||||
}
|
||||
|
||||
// countEnabled 统计启用 channel 数;main 启动摘要用。
|
||||
func countEnabled(chs []route.Channel) int {
|
||||
n := 0
|
||||
for _, c := range chs {
|
||||
if c.Enabled() {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
log.SetPrefix("[TTS-Server] ")
|
||||
@@ -61,6 +73,31 @@ func main() {
|
||||
return nil
|
||||
})
|
||||
|
||||
// 3.1) 阶段 1:多渠道路由器注入。
|
||||
// - 从 store 加载全部 channels(含 disabled,便于阶段 2 管理接口看全量);
|
||||
// router 内部筛 enabled
|
||||
// - channels 加载失败(如 credentials_json 损坏)→ 启动期 fail-fast,
|
||||
// 避免一个错凭据把每次请求搞崩
|
||||
// - 加载成功但列表为空 → 仍注入 router,但 router.Empty()=true,
|
||||
// controller 走"零渠道兜底",行为=阶段 0(向后兼容验收硬要求)
|
||||
if st != nil {
|
||||
chs, err := st.ChannelList(true)
|
||||
if err != nil {
|
||||
log.Fatalf("FATAL: load channels failed: %v", err)
|
||||
}
|
||||
routerChs := make([]route.Channel, 0, len(chs))
|
||||
for _, sc := range chs {
|
||||
rc, convErr := route.FromStoreChannel(sc)
|
||||
if convErr != nil {
|
||||
log.Fatalf("FATAL: convert channel id=%d name=%s failed: %v", sc.ID, sc.Name, convErr)
|
||||
}
|
||||
routerChs = append(routerChs, rc)
|
||||
}
|
||||
controller.SetRouter(route.NewRouter(routerChs))
|
||||
log.Printf("[main] 多渠道路由已注入: 共 %d 条 (enabled=%d)",
|
||||
len(routerChs), countEnabled(routerChs))
|
||||
}
|
||||
|
||||
// 4) M3: 从 store 加载运行时 TTS 配置(替代原来的 env-based InitTTSConfig)
|
||||
// 必须在 LogStartupSummary 之前,这样日志显示的是真实状态(API key 已从 DB 加载,不再读 env)
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user