feat(voice): M47 r1 探活地址单向回退到 voice-tts.json 的 baseUrl(组合根)
塔 2026-10-26 裁决:主人若把合成端口从 9880 改掉,不该还要记得两处一起改。 回退只做一向,且只发生在组合根(包内不互相读配置): 1. voice-tts-launch.json 显式写了 probeUrl ⇒ 以它为准,**永不**被别的键压过; 2. 没写 ⇒ 用 voice-tts.json 的 baseUrl(同一个服务); 3. 两者都空(或 voice-tts.json 坏掉)⇒ 默认 http://127.0.0.1:9880。 启动 Info 行同时打印 probe_url 与 probe_url_source(voice-tts-launch.json / voice-tts.json / default),一眼看出用的是哪个源。反向(拿这里地址去改合成面) 一律不做。VoiceTTSTuning 坏掉时只回落默认地址并 WARN,**不**因此关掉自启。 新增三条用例(均已变异验证打红): - ProbeURLInheritedFromVoiceTTS:真让探活打到自定义端口(hits>0),摘掉回退即红 - ProbeURLFallsBackToDefault:两者都空 ⇒ 9880 + source=default - ExplicitProbeURLWins:显式压过 baseUrl,且 baseUrl 一次都不被探
This commit is contained in:
1 parent
6906d274fc
commit
faf18afb91
2 files changed
+163
-1
No files matched your search
@@ -11,12 +11,16 @@ package main
|
||||
// 落不到后端的启动路径上。
|
||||
// 3. **失败只 WARN**:脚本不存在、起进程失败、探活超时都只是带 source 的日志,
|
||||
// 本函数**没有 error 返回**,绝不阻塞或改坏后端启动。
|
||||
// 4. **探活地址单向回退**(塔 2026-10-26 裁决,见 resolveProbeURL):launch 文件
|
||||
// 显式写了 `probeUrl` 就以它为准;没写则用 `voice-tts.json` 的 `baseUrl`;两者
|
||||
// 都空才是默认 9880。反向(拿这里的地址去改合成面)一律不做。
|
||||
//
|
||||
// 零新 `.env` 键(`.env` 已冻结):开关与脚本路径都走面板文件家族
|
||||
// (`runtimeconfig`,与 `voice-tts.json` 同一套读取口径)。
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/config/runtimeconfig"
|
||||
@@ -46,10 +50,14 @@ func (a *app) startVoiceTTSLaunch(ctx context.Context) *ttslaunch.Launcher {
|
||||
"path", runtimeconfig.VoiceTTSLaunchConfigRelPath, "hint", `set {"enabled": true}`)
|
||||
return nil
|
||||
}
|
||||
launcher := ttslaunch.New(voiceTTSLaunchConfig(tuning), ttslaunch.WithLogger(log))
|
||||
resolved := a.resolveProbeURL(tuning.ProbeURL)
|
||||
launcher := ttslaunch.New(withProbeURL(voiceTTSLaunchConfig(tuning), resolved), ttslaunch.WithLogger(log))
|
||||
cfg := launcher.Config()
|
||||
log.Info("emotionTTS auto-launch enabled",
|
||||
"probe_url", cfg.ProbeURL,
|
||||
// 探活地址可能来自三处,日志必须**同时**给出地址与来源:主人改端口后
|
||||
// 一眼能看出实际问的是哪个地址、以及它是显式写的还是兜底来的。
|
||||
"probe_url_source", resolved.probeSource,
|
||||
"script", cfg.ScriptPath,
|
||||
"probe_timeout_ms", cfg.ProbeTimeout.Milliseconds(),
|
||||
"cooldown_sec", int(cfg.Cooldown/time.Second),
|
||||
@@ -59,6 +67,56 @@ func (a *app) startVoiceTTSLaunch(ctx context.Context) *ttslaunch.Launcher {
|
||||
return launcher
|
||||
}
|
||||
|
||||
// probeResolution 是"探活地址 + 它的来源"(来源只用于日志,绝不参与判定)。
|
||||
type probeResolution struct {
|
||||
url string
|
||||
probeSource string
|
||||
}
|
||||
|
||||
// 探活地址的三个来源标签(写进启动 Info 行,供主人一眼核对)。
|
||||
const (
|
||||
probeSourceLaunchConfig = "voice-tts-launch.json"
|
||||
probeSourceVoiceTTS = "voice-tts.json"
|
||||
probeSourceDefault = "default"
|
||||
)
|
||||
|
||||
// resolveProbeURL 决定这次到底探哪个地址 —— **单向**回退,且只在组合根发生:
|
||||
//
|
||||
// 1. `voice-tts-launch.json` 显式写了 `probeUrl` ⇒ 用它(**永不**被别的键压过);
|
||||
// 2. 没写 ⇒ 兜底用 `voice-tts.json` 的 `baseUrl`(同一个服务,主人换端口只该改
|
||||
// 一处;这正是"两处一起改"的 footgun 的收口);
|
||||
// 3. 两者都没写(或 voice-tts.json 坏了)⇒ 空串,由 `ttslaunch.Config.Normalized`
|
||||
// 补默认 `http://127.0.0.1:9880`。
|
||||
//
|
||||
// 🔴 只做这一向:反向(拿 launch 的地址去改 `voice-tts.json` 的 `baseUrl`,或用它
|
||||
// 顶替合成地址)一律不做 —— 合成面与"起没起"是两个问题,前者不能被后者的配置影响。
|
||||
func (a *app) resolveProbeURL(explicit string) probeResolution {
|
||||
if url := strings.TrimSpace(explicit); url != "" {
|
||||
return probeResolution{url: url, probeSource: probeSourceLaunchConfig}
|
||||
}
|
||||
log := logger.WithSource(a.log, voiceTTSLaunchSource)
|
||||
tuning, err := runtimeconfig.LoadVoiceTTSTuning(runtimeconfig.DefaultVoiceTTSPath(resolveDataDir(a.cfg)))
|
||||
if err != nil {
|
||||
// 坏文件 ⇒ 这里只回落默认地址(**不**因此关掉自启:那是 launch 文件自己的
|
||||
// 事),并且必须说清楚"我没读到 baseUrl"。
|
||||
log.Warn("voice tts config unreadable, probe url falls back to default",
|
||||
"path", runtimeconfig.VoiceTTSConfigRelPath, "err", err)
|
||||
return probeResolution{probeSource: probeSourceDefault}
|
||||
}
|
||||
if base := strings.TrimSpace(tuning.BaseURL); base != "" {
|
||||
log.Debug("probe url inherited from voice tts config",
|
||||
"path", runtimeconfig.VoiceTTSConfigRelPath, "base_url", base)
|
||||
return probeResolution{url: base, probeSource: probeSourceVoiceTTS}
|
||||
}
|
||||
return probeResolution{probeSource: probeSourceDefault}
|
||||
}
|
||||
|
||||
// withProbeURL 把解析出的探活地址填进 launcher 配置(空串留给 Normalized 补默认)。
|
||||
func withProbeURL(cfg ttslaunch.Config, r probeResolution) ttslaunch.Config {
|
||||
cfg.ProbeURL = r.url
|
||||
return cfg
|
||||
}
|
||||
|
||||
// voiceTTSLaunchConfig 把面板形状映射成 launcher 的配置。
|
||||
//
|
||||
// 它**不**在这里裁决缺省值(脚本路径/探活地址/超时/冷却的默认值全在
|
||||
|
||||
Reference in new issue
Block a user