109 lines
4.8 KiB
Go
109 lines
4.8 KiB
Go
package grpc
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
|
||
activityv1 "hyapp.local/api/proto/activity/v1"
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/xerr"
|
||
broadcastservice "hyapp/services/activity-service/internal/service/broadcast"
|
||
)
|
||
|
||
// BroadcastServer 把 IM 播报能力暴露为内部 gRPC。
|
||
// 外部 HTTP 不直接调用这里;gateway/cron/room-service 只能通过 protobuf 契约进入 activity-service。
|
||
type BroadcastServer struct {
|
||
activityv1.UnimplementedBroadcastServiceServer
|
||
activityv1.UnimplementedRoomEventConsumerServiceServer
|
||
|
||
svc *broadcastservice.Service
|
||
}
|
||
|
||
// NewBroadcastServer 创建播报和 room event 消费共用的 gRPC adapter。
|
||
func NewBroadcastServer(svc *broadcastservice.Service) *BroadcastServer {
|
||
return &BroadcastServer{svc: svc}
|
||
}
|
||
|
||
func (s *BroadcastServer) EnsureBroadcastGroups(ctx context.Context, req *activityv1.EnsureBroadcastGroupsRequest) (*activityv1.EnsureBroadcastGroupsResponse, error) {
|
||
// app_code 只从 RequestMeta 进入 context,底层 repository 才能自动带上租户隔离条件。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
count, err := s.svc.EnsureBroadcastGroups(ctx)
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.EnsureBroadcastGroupsResponse{EnsuredCount: int32(count)}, nil
|
||
}
|
||
|
||
func (s *BroadcastServer) PublishRegionBroadcast(ctx context.Context, req *activityv1.PublishRegionBroadcastRequest) (*activityv1.PublishBroadcastResponse, error) {
|
||
// 区域播报是红包、贵重礼物等高频入口,gRPC 层只做字段搬运,策略留给 service。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
result, err := s.svc.PublishRegionBroadcast(ctx, broadcastservice.PublishInput{
|
||
EventID: req.GetEventId(),
|
||
BroadcastType: req.GetBroadcastType(),
|
||
RegionID: req.GetRegionId(),
|
||
PayloadJSON: req.GetPayloadJson(),
|
||
})
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.PublishBroadcastResponse{EventId: result.EventID, GroupId: result.GroupID, Status: result.Status, Created: result.Created}, nil
|
||
}
|
||
|
||
func (s *BroadcastServer) PublishGlobalBroadcast(ctx context.Context, req *activityv1.PublishGlobalBroadcastRequest) (*activityv1.PublishBroadcastResponse, error) {
|
||
// 全局播报和区域播报共用返回结构,调用方通过 group_id/status/created 判断幂等结果。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
result, err := s.svc.PublishGlobalBroadcast(ctx, broadcastservice.PublishInput{
|
||
EventID: req.GetEventId(),
|
||
BroadcastType: req.GetBroadcastType(),
|
||
PayloadJSON: req.GetPayloadJson(),
|
||
})
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.PublishBroadcastResponse{EventId: result.EventID, GroupId: result.GroupID, Status: result.Status, Created: result.Created}, nil
|
||
}
|
||
|
||
func (s *BroadcastServer) RemoveRegionBroadcastMember(ctx context.Context, req *activityv1.RemoveRegionBroadcastMemberRequest) (*activityv1.RemoveRegionBroadcastMemberResponse, error) {
|
||
// 这里只删除 user_id 在旧区域群的成员关系,不删除区域群;群生命周期仍由 reconciler 管理。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
groupID, removed, err := s.svc.RemoveRegionBroadcastMember(ctx, req.GetUserId(), req.GetRegionId())
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.RemoveRegionBroadcastMemberResponse{GroupId: groupID, Removed: removed}, nil
|
||
}
|
||
|
||
func (s *BroadcastServer) ProcessBroadcastOutboxBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.ProcessBroadcastOutboxBatchResponse, error) {
|
||
// cron-service 可以显式触发一批投递;常驻 worker 也复用同一个 service 方法。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
result, err := s.svc.ProcessPendingBroadcasts(ctx, broadcastservice.WorkerOptions{
|
||
WorkerID: req.GetWorkerId(),
|
||
BatchSize: int(req.GetBatchSize()),
|
||
LockTTL: time.Duration(req.GetLockTtlMs()) * time.Millisecond,
|
||
})
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.ProcessBroadcastOutboxBatchResponse{
|
||
ClaimedCount: int32(result.ClaimedCount),
|
||
SuccessCount: int32(result.SuccessCount),
|
||
FailureCount: int32(result.FailureCount),
|
||
HasMore: result.HasMore,
|
||
}, nil
|
||
}
|
||
|
||
func (s *BroadcastServer) ConsumeRoomEvent(ctx context.Context, req *activityv1.ConsumeRoomEventRequest) (*activityv1.ConsumeRoomEventResponse, error) {
|
||
// room-service 只推送已提交的 outbox envelope;是否播报、播给哪个群由 activity-service 判定。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
result, err := s.svc.HandleRoomEvent(ctx, req.GetEnvelope())
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.ConsumeRoomEventResponse{
|
||
EventId: result.EventID,
|
||
Status: result.Status,
|
||
BroadcastEventId: result.BroadcastEventID,
|
||
BroadcastCreated: result.BroadcastCreated,
|
||
}, nil
|
||
}
|