1 Commits

Author SHA1 Message Date
lpf
c1cbec551b fix 2026-05-11 13:27:31 +08:00
2 changed files with 56 additions and 1 deletions

View File

@@ -4,9 +4,12 @@ import (
"context"
"os"
"path/filepath"
"reflect"
"sync/atomic"
"testing"
"time"
"github.com/YspCoder/clawgo/pkg/config"
)
func TestConfigFileFingerprintSameContentIgnoresTouch(t *testing.T) {
@@ -115,3 +118,43 @@ func TestGatewayConfigWatcherTouchDoesNotReload(t *testing.T) {
t.Fatalf("expected touch-only update to skip reload, got %d", got)
}
}
func TestNormalizeHotReloadChannelsConfigIgnoresWeixinRuntimeState(t *testing.T) {
t.Parallel()
base := config.ChannelsConfig{
Weixin: config.WeixinConfig{
Enabled: true,
BaseURL: "https://ilinkai.weixin.qq.com",
DefaultBotID: "bot-a",
Accounts: []config.WeixinAccountConfig{
{
BotID: "bot-a",
BotToken: "token-a",
IlinkUserID: "u-1",
ContextToken: "ctx-a",
GetUpdatesBuf: "buf-a",
},
},
ContextToken: "root-ctx",
GetUpdatesBuf: "root-buf",
},
}
next := base
next.Weixin.ContextToken = "root-ctx-next"
next.Weixin.GetUpdatesBuf = "root-buf-next"
next.Weixin.Accounts[0].ContextToken = "ctx-b"
next.Weixin.Accounts[0].GetUpdatesBuf = "buf-b"
left := normalizeHotReloadChannelsConfig(base)
right := normalizeHotReloadChannelsConfig(next)
if !reflect.DeepEqual(left, right) {
t.Fatalf("expected weixin runtime state changes to be ignored during hot reload comparison")
}
next.Weixin.BaseURL = "https://redirect.example"
right = normalizeHotReloadChannelsConfig(next)
if reflect.DeepEqual(left, right) {
t.Fatalf("expected durable weixin config changes to remain visible to hot reload comparison")
}
}

View File

@@ -67,10 +67,12 @@ func (r *gatewayReloader) trigger(source string, forceRuntimeReload bool) error
r.state.cfg.Gateway.Host, r.state.cfg.Gateway.Port, newCfg.Gateway.Host, newCfg.Gateway.Port)
}
currentChannels := normalizeHotReloadChannelsConfig(r.state.cfg.Channels)
nextChannels := normalizeHotReloadChannelsConfig(newCfg.Channels)
runtimeSame := reflect.DeepEqual(r.state.cfg.Agents, newCfg.Agents) &&
reflect.DeepEqual(r.state.cfg.Models, newCfg.Models) &&
reflect.DeepEqual(r.state.cfg.Tools, newCfg.Tools) &&
reflect.DeepEqual(r.state.cfg.Channels, newCfg.Channels)
reflect.DeepEqual(currentChannels, nextChannels)
if runtimeSame && !forceRuntimeReload {
configureLogging(newCfg)
@@ -146,6 +148,16 @@ func (r *gatewayReloader) bindWeixinChannel() {
}
}
func normalizeHotReloadChannelsConfig(cfg config.ChannelsConfig) config.ChannelsConfig {
cfg.Weixin.ContextToken = ""
cfg.Weixin.GetUpdatesBuf = ""
for i := range cfg.Weixin.Accounts {
cfg.Weixin.Accounts[i].ContextToken = ""
cfg.Weixin.Accounts[i].GetUpdatesBuf = ""
}
return cfg
}
type configFileFingerprint struct {
Size int64
ModUnixNano int64