2026-06-26 23:21:22 +08:00

54 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package integration
import (
"context"
"hash/fnv"
"sync"
roomeventsv1 "hyapp.local/api/proto/events/room/v1"
)
// ShardedOutboxPublisher 只在 IM bridge 侧使用:不同 room_id 可以并发,同一个房间仍串行调用下游发布器。
type ShardedOutboxPublisher struct {
inner OutboxPublisher
locks []sync.Mutex
}
// NewShardedOutboxPublisher 用 room_id 分片保护下游发布器的房间内顺序concurrency<=1 时保持历史串行实现。
func NewShardedOutboxPublisher(inner OutboxPublisher, concurrency int) OutboxPublisher {
if inner == nil {
return NewNoopOutboxPublisher()
}
if concurrency <= 1 {
return inner
}
return &ShardedOutboxPublisher{
inner: inner,
locks: make([]sync.Mutex, concurrency),
}
}
// PublishOutboxEvent 对同一 room_id 使用同一把锁,避免 RocketMQ consumer 并发后把礼物和麦位展示乱序发给腾讯 IM。
func (p *ShardedOutboxPublisher) PublishOutboxEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) error {
if p == nil || p.inner == nil || envelope == nil {
return nil
}
if len(p.locks) == 0 {
return p.inner.PublishOutboxEvent(ctx, envelope)
}
lock := &p.locks[p.shardIndex(envelope.GetRoomId())]
lock.Lock()
defer lock.Unlock()
return p.inner.PublishOutboxEvent(ctx, envelope)
}
func (p *ShardedOutboxPublisher) shardIndex(roomID string) uint32 {
if len(p.locks) == 1 {
return 0
}
hash := fnv.New32a()
_, _ = hash.Write([]byte(roomID))
return hash.Sum32() % uint32(len(p.locks))
}