hyapp-server/services/room-service/internal/room/service/robot_display_publisher.go
2026-06-26 23:21:22 +08:00

69 lines
2.2 KiB
Go

package service
import (
"context"
"log/slog"
"time"
"hyapp/pkg/appcode"
"hyapp/pkg/logx"
"hyapp/services/room-service/internal/room/outbox"
)
const (
// robotDisplayPublishTimeout 是机器人展示直发 IM 的单条上限;超时或失败只记日志,不影响已提交房间状态。
robotDisplayPublishTimeout = 3 * time.Second
)
func (s *Service) publishRobotDisplayRecordsBestEffort(ctx context.Context, records []outbox.Record) {
if s == nil || len(records) == 0 {
return
}
if s.robotDisplayPublisher == nil {
// 缺少腾讯 IM publisher 时不能阻断房间命令,只把整批展示事件视为 best-effort 投递失败。
logx.Warn(ctx, "robot_display_im_publish_skipped",
slog.String("node_id", s.nodeID),
slog.Int("record_count", len(records)),
slog.String("reason", "publisher_not_configured"),
)
return
}
scopedApp := appcode.FromContext(ctx)
copied := append([]outbox.Record(nil), records...)
for index := range copied {
copied[index].AppCode = appcode.Normalize(firstNonEmpty(copied[index].AppCode, scopedApp))
if copied[index].Envelope != nil {
copied[index].Envelope.AppCode = copied[index].AppCode
}
}
sortOutboxRecords(copied)
go func(records []outbox.Record) {
for _, record := range records {
if record.Envelope == nil {
logx.Warn(ctx, "robot_display_im_publish_skipped",
slog.String("node_id", s.nodeID),
slog.String("event_id", record.EventID),
slog.String("event_type", record.EventType),
slog.String("room_id", record.RoomID),
slog.String("reason", "nil_envelope"),
)
continue
}
publishCtx, cancel := context.WithTimeout(appcode.WithContext(context.Background(), record.AppCode), robotDisplayPublishTimeout)
err := s.robotDisplayPublisher.PublishOutboxEvent(publishCtx, record.Envelope)
cancel()
if err != nil {
// 机器人展示事件允许极小概率丢失;这里只暴露日志,客户端靠房间快照恢复最终状态。
logx.Warn(ctx, "robot_display_im_publish_failed",
slog.String("node_id", s.nodeID),
slog.String("event_id", record.EventID),
slog.String("event_type", record.EventType),
slog.String("room_id", record.RoomID),
slog.String("error", trimOutboxError(err.Error())),
)
}
}
}(copied)
}