重构:main.go 直接 import 各 internal/ 子包,删除全部 bridge

最后一步:把 main.go 里所有指向桥接小写名的引用(store / config /
blocking / bot / runtimesettings / mqttforward / web 等)改写成直接调用
internal/* 子包的导出 API,从而拆掉所有 *_bridge.go。

变更点
- main.go 顶部 import 区改为引用 11 个 internal/ 子包:auth、blocking、
  bot、config、mqttforward、runtimesettings、store、web 等。
- meshtasticFilterHook 字段类型改为 *storepkg.WriteQueue / *blockingpkg.Cache
  / *rspkg.Cache / *mqttforwardpkg.Stats;不再依赖 main 包内别名。
- mqttClientInfoFromClient 返回 storepkg.MQTTClientInfo(之前为 main 包别名)。
- run() 里 newSessionManager → auth.NewManager;newRouter → webpkg.NewRouter;
  serveHTTPUnixSocket → webpkg.ServeUnixSocket;mqttRuntimeStatus →
  webpkg.MQTTRuntimeStatus;botSendTextRequest → botpkg.SendTextRequest;
  newBlockingCache / newRuntimeSettingsCache / newMQTTForwardManager 都改为
  对应包的 New / NewManager。
- main_test.go 里的 BlockingViolationForRecord 测试改用 testutil.OpenStore
  + blockingpkg.New,全部通过 store.Store 的公开 API 构造数据,不再需要
  根目录 test_helpers_test.go。

删除根目录文件
- config.go、auth.go(已删)、blocking_bridge.go、bot_bridge.go、
  help_bridge.go、llmadmin_bridge.go、mapsource_bridge.go、
  mqttforward_bridge.go、runtime_settings_bridge.go、sign_bridge.go、
  store_bridge.go、web_bridge.go、test_helpers_test.go。

最终结果
- 根目录只剩 main.go (~370 行) 和 main_test.go (~110 行)。
- internal/ 下 13 个独立子包:auth / blocking / bot / config / help /
  llmadmin / mapsource / mqttforward / runtimesettings / sign / store /
  store/testutil / web / webutil。
- go build ./... / go test ./... 全部通过;测试数量与重构前一致;
  go build . 可以产出可执行二进制(约 50 MB)。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-18 18:30:00 +08:00
co-authored by Claude
parent 9394aa0f4a
commit 46916d9a93
14 changed files with 70 additions and 480 deletions
+16 -13
View File
@@ -4,11 +4,15 @@ import (
"testing"
mqtt "github.com/mochi-mqtt/server/v2"
blockingpkg "meshtastic_mqtt_server/internal/blocking"
storepkg "meshtastic_mqtt_server/internal/store"
"meshtastic_mqtt_server/internal/store/testutil"
)
func TestMQTTClientInfoFromClientNil(t *testing.T) {
info := mqttClientInfoFromClient(nil)
if info != (mqttClientInfo{}) {
if info != (storepkg.MQTTClientInfo{}) {
t.Fatalf("info = %#v, want zero value", info)
}
}
@@ -42,20 +46,19 @@ func TestMQTTClientInfoFromClientUnsplitRemote(t *testing.T) {
}
}
// 注:blockingViolationForRecord 的测试现在跟着 blockingCache 一起搬到了
// internal/blocking/violations_test.go,使用真实 *Store 构造缓存而不是
// 直接捏造未导出字段。这里保留 mqtt client info 这部分测试不动。
// blockingViolationForRecord 的测试用真实 *Store + blocking.Cache 走完整路径,
// 不依赖 cache 的未导出字段。
func TestBlockingViolationForRecordNode(t *testing.T) {
st := openTestStore(t)
st := testutil.OpenStore(t)
defer st.Close()
nodeNum := int64(305419896)
if _, err := st.CreateNodeBlocking("!12345678", &nodeNum, "blocked", true); err != nil {
t.Fatalf("CreateNodeBlocking() error = %v", err)
}
cache, err := newBlockingCache(st)
cache, err := blockingpkg.New(st)
if err != nil {
t.Fatalf("newBlockingCache() error = %v", err)
t.Fatalf("blocking.New() error = %v", err)
}
record := map[string]any{"type": "position", "from": "!12345678", "from_num": uint32(305419896)}
violation := blockingViolationForRecord(cache, record)
@@ -65,14 +68,14 @@ func TestBlockingViolationForRecordNode(t *testing.T) {
}
func TestBlockingViolationForRecordForbiddenWordFields(t *testing.T) {
st := openTestStore(t)
st := testutil.OpenStore(t)
defer st.Close()
if _, err := st.CreateForbiddenWordBlocking("spam", "contains", false, "blocked", true); err != nil {
t.Fatalf("CreateForbiddenWordBlocking() error = %v", err)
}
cache, err := newBlockingCache(st)
cache, err := blockingpkg.New(st)
if err != nil {
t.Fatalf("newBlockingCache() error = %v", err)
t.Fatalf("blocking.New() error = %v", err)
}
for _, tc := range []struct {
@@ -94,14 +97,14 @@ func TestBlockingViolationForRecordForbiddenWordFields(t *testing.T) {
}
func TestBlockingViolationForRecordAllowed(t *testing.T) {
st := openTestStore(t)
st := testutil.OpenStore(t)
defer st.Close()
if _, err := st.CreateForbiddenWordBlocking("spam", "contains", false, "blocked", true); err != nil {
t.Fatalf("CreateForbiddenWordBlocking() error = %v", err)
}
cache, err := newBlockingCache(st)
cache, err := blockingpkg.New(st)
if err != nil {
t.Fatalf("newBlockingCache() error = %v", err)
t.Fatalf("blocking.New() error = %v", err)
}
record := map[string]any{"type": "text_message", "from": "!1", "text": "hello"}
if violation := blockingViolationForRecord(cache, record); violation != nil {