32 lines
1.7 KiB
Go
32 lines
1.7 KiB
Go
package channelbridge
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/hex"
|
||
"time"
|
||
)
|
||
|
||
// 本文件承载 IM 车道自己的**回合标识**生成点(design/15 §2.5.9)。
|
||
//
|
||
// IM 与 Web 是两条独立的驱动路径:Web 由 gateway 编排器起路、由它生成权威 turnId
|
||
// (gateway/ws_hub_turn.go 的 newTurnID),而 IM 由渠道桥自己驱动 loop
|
||
// (inbound.go 的 runInboundTurn → b.run.Run)—— 桥接器就是**这条车道的回合权威**,
|
||
// 因此这里生成的是真实归属:一条入站消息 → 一次 run → 一条回复,标识只在这一段
|
||
// 生命周期内有效。绝不拿时间戳或会话 id 冒充 turn id —— 那是伪造归属,比留空更坏
|
||
// (留空诚实地表示「不属于任何已知回合」,冒充则会让两个不同回合被分进同一桶)。
|
||
//
|
||
// 格式与 gateway 那份**逐字一致**(`turn-` + 16 位十六进制),使两条车道产出的
|
||
// turnId 对任何消费方(前端按 (sessionId, turnId) 两级分桶)都是同一种东西。它成为
|
||
// 第二处副本,是因为 gateway 那份未导出、且该包已冻结,无法共享 —— 不是有意另造。
|
||
|
||
// newTurnID 返回一个新的随机十六进制回合标识,用于把一次 IM 入站回合的落库行
|
||
// (用户消息 + 助手回复)关联到同一路。它消耗 crypto/rand 源,源不可用时回退到
|
||
// 纳秒时间戳,因此总能产出 id —— 空的 turnId 会静默破坏客户端的两级分桶。
|
||
func newTurnID() string {
|
||
var b [8]byte
|
||
if _, err := rand.Read(b[:]); err == nil {
|
||
return "turn-" + hex.EncodeToString(b[:])
|
||
}
|
||
return "turn-" + time.Now().UTC().Format("20060102150405.000000000")
|
||
}
|