107 lines
3.0 KiB
Go

package registerreward
import "sync"
// registerRewardNoticeHub 维护本地调试页订阅的通知监听器。
// 这里使用进程内广播,目的是在不接入 App IM SDK 的前提下,也能验证
// “注册成功 -> Go 发奖 -> Go 发 REGISTER_REWARD_GRANTED 通知”这条链路是否打通。
type registerRewardNoticeHub struct {
mu sync.RWMutex
subscribers map[int64]map[chan RegisterRewardNoticeEvent]struct{}
recent map[int64][]RegisterRewardNoticeEvent
}
// newRegisterRewardNoticeHub 创建进程内通知广播中心。
func newRegisterRewardNoticeHub() *registerRewardNoticeHub {
return &registerRewardNoticeHub{
subscribers: make(map[int64]map[chan RegisterRewardNoticeEvent]struct{}),
recent: make(map[int64][]RegisterRewardNoticeEvent),
}
}
// subscribe 按 userId 订阅注册奖励通知镜像。
func (h *registerRewardNoticeHub) subscribe(userID int64) (<-chan RegisterRewardNoticeEvent, func()) {
stream := make(chan RegisterRewardNoticeEvent, 16)
h.mu.Lock()
recent := append([]RegisterRewardNoticeEvent(nil), h.recent[userID]...)
if _, ok := h.subscribers[userID]; !ok {
h.subscribers[userID] = make(map[chan RegisterRewardNoticeEvent]struct{})
}
h.subscribers[userID][stream] = struct{}{}
h.mu.Unlock()
for _, event := range recent {
select {
case stream <- event:
default:
}
}
cancel := func() {
h.mu.Lock()
defer h.mu.Unlock()
group, ok := h.subscribers[userID]
if !ok {
return
}
if _, exists := group[stream]; exists {
delete(group, stream)
close(stream)
}
if len(group) == 0 {
delete(h.subscribers, userID)
}
}
return stream, cancel
}
// publish 把通知镜像广播给当前用户的所有本地订阅者。
// 这里使用非阻塞写入,避免测试页断开或消费变慢时反向卡住正式发奖链路。
func (h *registerRewardNoticeHub) publish(event RegisterRewardNoticeEvent) {
if event.UserID <= 0 {
return
}
h.mu.Lock()
h.recent[event.UserID] = append(h.recent[event.UserID], event)
if len(h.recent[event.UserID]) > 10 {
h.recent[event.UserID] = append([]RegisterRewardNoticeEvent(nil), h.recent[event.UserID][len(h.recent[event.UserID])-10:]...)
}
group := h.subscribers[event.UserID]
targets := make([]chan RegisterRewardNoticeEvent, 0, len(group))
for stream := range group {
targets = append(targets, stream)
}
h.mu.Unlock()
for _, stream := range targets {
select {
case stream <- event:
default:
}
}
}
// SubscribeDebugNotices 给本地测试页提供注册奖励通知订阅能力。
func (s *RegisterRewardService) SubscribeDebugNotices(userID int64) (<-chan RegisterRewardNoticeEvent, func()) {
if s == nil || s.debug == nil {
closed := make(chan RegisterRewardNoticeEvent)
close(closed)
return closed, func() {}
}
return s.debug.subscribe(userID)
}
// publishDebugNotice 把刚刚触发的 REGISTER_REWARD_GRANTED 镜像到本地调试流。
func (s *RegisterRewardService) publishDebugNotice(event RegisterRewardNoticeEvent) {
if s == nil || s.debug == nil {
return
}
s.debug.publish(event)
}