docs(comments): 注释中文化 · internal/services/channelbridge(纯替换)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 只翻注释/文档字符串:剥掉注释后代码行逐字节不变(机械校验只剩允许的行尾注释形态)
- 术语对齐既有译法(owner→主人、persona→角色、engage→参与度判定、quiet hours→安静时段、backoff→退避)
- 复核:go build 绿 + channelbridge 包测试绿;gofmt 干净
This commit is contained in:
AskaEth committed 2026-10-04 13:33:06 +08:00
1 parent 61cf80d5ee
commit 093f38d986
28 files changed
+1089 -1089

No files matched your search

+48 -48
View File
@@ -1,12 +1,12 @@
package channelbridge
// This file holds the hot-reload machinery for the channel bridge (design/04
// §3.1). The panel saves a platform's account config to channels.json and calls
// Bridge.Reload(platform): the factory rebuilds that platform's adapters, they
// connect first (new messages use the new config), then the old adapters are
// gracefully stopped. A message already in flight finishes on its old adapter
// because processing is spawned with the bridge-lifetime context, not the
// per-adapter read context that reload cancels.
// 本文件承载渠道桥接器的热重载机制(design/04
// §3.1)。面板把某平台的账号配置保存到 channels.json 并调用
// Bridge.Reload(platform):工厂重建该平台的适配器,它们
// 先连接(新消息使用新配置),随后旧适配器
// 被优雅停止。已在途的消息仍在其旧适配器上完成,
// 因为消息处理是以桥接器生命周期 context 派生的,而非
// 重载所取消的按适配器读取 context。
import (
"context"
@@ -16,29 +16,29 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter"
)
// PlatformFactory rebuilds the adapters for a platform from its current effective
// account config (channels.json, falling back to env). It is injected so the
// bridge can hot-replace a platform's adapters when the panel saves a new config
// without a restart. The concrete implementation lives in the composition root
// (cmd/cyrene), which owns the platform adapter constructors.
// PlatformFactory 依据平台当前生效的账号配置
// (channels.json,回退到环境变量)重建其适配器。它以注入方式提供,
// 使桥接器能在面板保存新配置时热替换该平台的适配器
// 而无需重启。具体实现位于组合根
// (cmd/cyrene),平台适配器的构造函数由那里持有。
type PlatformFactory interface {
// Build returns the adapters for platform from its effective account config.
// The returned slice may be empty when the platform has no configured account.
// Build 依据生效的账号配置返回该平台的适配器。
// 平台没有已配置账号时,返回的切片可能为空。
Build(platform string) ([]adapter.PlatformAdapter, error)
}
// ErrNilFactory is returned when a reload is requested without a platform factory
// injected (no hot-reload configuration source).
// ErrNilFactory 表示请求重载时未注入平台工厂
// (没有热重载配置来源)。
var ErrNilFactory = errors.New("channelbridge: nil platform factory")
// ErrBridgeClosed is returned when a reload is requested on a stopped bridge.
// ErrBridgeClosed 表示在已停止的桥接器上请求重载。
var ErrBridgeClosed = errors.New("channelbridge: bridge is not running")
// connectAndRun dials a single adapter (bound by connectTimeout) and, on success,
// installs its inbound handler and launches its read loop under a per-adapter
// context. The per-adapter context is what a hot reload cancels to stop the old
// read loop; message processing is spawned with the bridge-lifetime context so an
// in-flight message started before a Reload completes on its old adapter.
// connectAndRun 拨号单个适配器(受 connectTimeout 约束),成功时
// 装配其入站处理器,并在按适配器 context 下启动其读取
// 循环。热重载正是取消这个按适配器 context 来停止旧
// 读取循环;消息处理则以桥接器生命周期 context 派生,
// 因此 Reload 之前已在途的消息会在其旧适配器上完成。
func (b *Bridge) connectAndRun(a adapter.PlatformAdapter) {
if a == nil {
return
@@ -56,9 +56,9 @@ func (b *Bridge) connectAndRun(a adapter.PlatformAdapter) {
return
}
// Close over the adapter so the inbound callback knows which account received
// the message — required for multi-account reply routing and for reading that
// account's allow/deny lists (design/16 §4.6 §5).
// 闭包捕获该适配器,使入站回调知道是哪个账号收到了
// 消息——多账号回复路由,以及读取该账号的
// 允许/拒绝名单都依赖它(design/16 §4.6 §5)。
a.SetMessageHandler(func(_ context.Context, msg adapter.UnifiedMessage) {
b.onMessage(b.ctx, msg, a)
})
@@ -74,21 +74,21 @@ func (b *Bridge) connectAndRun(a adapter.PlatformAdapter) {
b.readCancels[a.Name()] = rcancel
b.connected[a.Name()] = true
b.mu.Unlock()
// Cache the account's channel-level role now that the adapter is live: the
// inbound path reads the cache instead of the config, and a reload (which the
// panel's save triggers) re-runs this to pick up a new binding.
// 适配器已上线,此时缓存该账号的渠道级角色:
// 入站路径读取缓存而不是配置,而重载(由面板保存
// 触发)会重跑这里以拾取新的绑定。
b.rememberAdapterPersona(a.Name())
b.wg.Add(1)
go b.readLoop(a, readCtx)
b.log.Info("channel connected", "channel", a.Name())
}
// Reload rebuilds the adapters for a platform from its current effective config
// (via the injected factory) and hot-replaces the running ones without a restart
// (design/04 §3.1). The rebuilt adapters connect first; messages that arrived on
// the old adapters finish on them, and new messages are picked up by the new
// configuration. An account that was removed stops its old adapter, and an
// unchanged-name account stops the old adapter once the new one is live.
// Reload 依据平台当前生效的配置(经由注入的工厂)重建其适配器,
// 并在不重启的前提下热替换正在运行的适配器
// (design/04 §3.1)。重建后的适配器先连接;到达旧适配器的
// 消息在旧适配器上完成,新消息则由新配置
// 接管。被移除的账号会停掉其旧适配器;名称未变的
// 账号在新适配器上线后停掉旧适配器。
func (b *Bridge) Reload(platform string) error {
if b.factory == nil {
return ErrNilFactory
@@ -115,22 +115,22 @@ func (b *Bridge) Reload(platform string) error {
}
for _, o := range old {
if newNames[o.Name()] {
// Same-name account replaced by the rebuilt adapter: stop the old read
// loop but leave the registry entry — it now points at the new adapter.
// 同名账号被重建后的适配器替换:停止旧的读取
// 循环,但保留注册表条目——它现在指向新适配器。
b.cancelAndDisconnect(o, oldCancels[o.Name()])
continue
}
// Account removed (or renamed) entirely: stop it and drop its registry
// entries, so a subsequent snapshot no longer sees it.
// 账号被彻底移除(或更名):停止它并删除其注册表
// 条目,后续 snapshot 便不再看到它。
b.removeAdapter(o, oldCancels[o.Name()])
}
b.log.Info("channel reloaded", "platform", platform, "adapters", len(newAdapters))
return nil
}
// adapterSnap returns the adapters currently registered for a platform, together
// with the context-cancel func that controls each one's read loop. It is used by
// Reload to stop the old adapters after the rebuilt ones are live.
// adapterSnap 返回某平台当前已注册的适配器,以及
// 控制各自读取循环的 context 取消函数。Reload 用它
// 在重建的适配器上线后停止旧适配器。
func (b *Bridge) adapterSnap(platform string) ([]adapter.PlatformAdapter, map[string]context.CancelFunc) {
b.mu.RLock()
defer b.mu.RUnlock()
@@ -148,10 +148,10 @@ func (b *Bridge) adapterSnap(platform string) ([]adapter.PlatformAdapter, map[st
return list, cancels
}
// cancelAndDisconnect stops an adapter's read loop and tears down its session.
// It never touches the registry map: callers that replace a same-name adapter
// want the (new) entry to stay, and callers that remove an account use
// removeAdapter.
// cancelAndDisconnect 停止适配器的读取循环并拆除其会话。
// 它绝不改动注册表 map:替换同名适配器的调用方
// 希望(新)条目保留,而移除账号的调用方使用
// removeAdapter。
func (b *Bridge) cancelAndDisconnect(o adapter.PlatformAdapter, c context.CancelFunc) {
if c != nil {
c()
@@ -162,9 +162,9 @@ func (b *Bridge) cancelAndDisconnect(o adapter.PlatformAdapter, c context.Cancel
b.log.Info("channel (reload) stopped", "channel", o.Name())
}
// removeAdapter stops an account's adapter and drops its registry entries. It is
// only called for names that were NOT rebuilt by Reload, so the delete can never
// remove a replacement adapter that now owns the name.
// removeAdapter 停止账号的适配器并删除其注册表条目。它
// 只对未被 Reload 重建的名称调用,因此删除绝不会
// 误删如今占用该名称的替换适配器。
func (b *Bridge) removeAdapter(o adapter.PlatformAdapter, c context.CancelFunc) {
b.cancelAndDisconnect(o, c)
name := o.Name()