package backthink // 生产组合根在 backthink.New *之后* 才构建 gateway hub 与 channel // bridge(hub 需要 loop,bridge 需要 loop 与主人档案, // 两者都在更晚时才组装),因此构造时拿不到 ActiveClient 与 // IMAdapter 槽。这些设置器在 gateway / bridge 存在后注入它们, // 并重建推送器,同时保留已解出的 // 频率门,使之后的推送路由正确。 // SetActiveSink 接入生产用的活跃 Web/原生客户端槽(gateway // hub)并重建推送器。请在 gateway 存在之后、Start 之前调用。 func (b *Backthink) SetActiveSink(active ActiveClient) { b.mu.Lock() defer b.mu.Unlock() b.deps.Active = active b.rebuildPusherLocked() } // SetIMSink 接入生产用的 IM 桥槽(channel bridge)并重建 // 推送器。请在 channel bridge 存在之后、Start 之前调用。 func (b *Backthink) SetIMSink(im IMAdapter) { b.mu.Lock() defer b.mu.Unlock() b.deps.IM = im b.rebuildPusherLocked() } // rebuildPusherLocked 用当前槽位、频率门与推送出口替换 // 推送器。调用方必须持有 b.mu。 func (b *Backthink) rebuildPusherLocked() { b.pusher = newPusher(b.deps.Active, b.deps.IM, b.gate, b.log).withExporter(b.deps.Exporter) } // currentPusher 在生命周期锁下返回当前推送器,因此一次槽位 // 换入绝不会与即将推送的并发思考轮发生竞态。 func (b *Backthink) currentPusher() Pusher { b.mu.Lock() defer b.mu.Unlock() return b.pusher }