2026-06-11 13:33:44 +08:00

137 lines
5.4 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 grpc
import (
"context"
"time"
userv1 "hyapp.local/api/proto/user/v1"
"hyapp/pkg/xerr"
userdomain "hyapp/services/user-service/internal/domain/user"
authservice "hyapp/services/user-service/internal/service/auth"
mictimeservice "hyapp/services/user-service/internal/service/mictime"
userservice "hyapp/services/user-service/internal/service/user"
)
// ProcessLoginIPRiskBatch 处理一批登录后 IP 风控任务,任务 claim 和 session revoke 仍在 user-service 内完成。
func (s *Server) ProcessLoginIPRiskBatch(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) {
ctx = contextWithApp(ctx, req.GetMeta())
if s.authSvc == nil {
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "auth service is not configured"))
}
processed, err := s.authSvc.ProcessLoginIPRiskBatch(ctx, authservice.LoginIPRiskWorkerOptions{
WorkerID: req.GetWorkerId(),
LockTTL: durationFromMillis(req.GetLockTtlMs()),
BatchSize: int(req.GetBatchSize()),
})
if err != nil {
return nil, xerr.ToGRPCError(err)
}
return &userv1.CronBatchResponse{
ClaimedCount: int32(processed),
ProcessedCount: int32(processed),
SuccessCount: int32(processed),
HasMore: processed >= normalizedBatchSize(req.GetBatchSize(), 100),
}, nil
}
// ProcessRegionRebuildBatch 处理一个区域重算分页任务,按 app_code 作用域 claim。
func (s *Server) ProcessRegionRebuildBatch(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) {
ctx = contextWithApp(ctx, req.GetMeta())
if s.userSvc == nil {
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "user service is not configured"))
}
result, err := s.userSvc.ProcessNextRegionRebuildTask(ctx, userservice.RegionRebuildWorkerOptions{
WorkerID: req.GetWorkerId(),
LockTTL: durationFromMillis(req.GetLockTtlMs()),
BatchSize: int(req.GetBatchSize()),
})
if err != nil {
return nil, xerr.ToGRPCError(err)
}
if result.NoTask {
return &userv1.CronBatchResponse{}, nil
}
return &userv1.CronBatchResponse{
ClaimedCount: 1,
ProcessedCount: int32(result.ProcessedUsers),
SuccessCount: 1,
HasMore: result.Status == userdomain.RegionRebuildTaskStatusPending,
}, nil
}
// CompensateMicOpenSessions 关闭异常长时间未收到 down 事件的用户麦位统计 session不反写 Room Cell。
func (s *Server) CompensateMicOpenSessions(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) {
ctx = contextWithApp(ctx, req.GetMeta())
if s.micTimeSvc == nil {
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "mic time service is not configured"))
}
result, err := s.micTimeSvc.ProcessOpenSessionCompensationBatch(ctx, mictimeservice.CompensationWorkerOptions{
WorkerID: req.GetWorkerId(),
BatchSize: int(req.GetBatchSize()),
PendingPublishMaxAge: durationFromMillis(req.GetPendingPublishMaxAgeMs()),
PublishingSessionMaxAge: durationFromMillis(req.GetPublishingSessionMaxAgeMs()),
})
if err != nil {
return nil, xerr.ToGRPCError(err)
}
return &userv1.CronBatchResponse{
ClaimedCount: int32(result.ClosedCount),
ProcessedCount: int32(result.ClosedCount),
SuccessCount: int32(result.ClosedCount),
HasMore: result.ClosedCount >= normalizedBatchSize(req.GetBatchSize(), 100),
}, nil
}
// ExpireManagerUserBlocks 释放到期的经理封禁记录;真正是否恢复 users.status 由 user-service 内部封禁来源判断。
func (s *Server) ExpireManagerUserBlocks(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) {
ctx = contextWithApp(ctx, req.GetMeta())
if s.userSvc == nil {
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "user service is not configured"))
}
processed, err := s.userSvc.ExpireManagerUserBlocks(ctx, req.GetBatchSize())
if err != nil {
return nil, xerr.ToGRPCError(err)
}
return &userv1.CronBatchResponse{
ClaimedCount: int32(processed),
ProcessedCount: int32(processed),
SuccessCount: int32(processed),
HasMore: processed >= normalizedBatchSize(req.GetBatchSize(), 100),
}, nil
}
// RefreshCPIntimacyLeaderboard 重建 CP 亲密值排行榜 Redis zsetcron-service 只负责调度和租约。
func (s *Server) RefreshCPIntimacyLeaderboard(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) {
// cron-service 每个 app_code 单独触发一次;这里把 app_code 放进 context 后MySQL 查询和 Redis key 都会按租户隔离。
ctx = contextWithApp(ctx, req.GetMeta())
if s.cpSvc == nil {
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "cp service is not configured"))
}
// batch_size 在这个任务里不是“继续翻页”的游标只是本轮榜单最大行数service 会全量替换 Redis 读模型。
processed, err := s.cpSvc.RefreshIntimacyLeaderboard(ctx, int(req.GetBatchSize()))
if err != nil {
return nil, xerr.ToGRPCError(err)
}
// 刷新是一次性快照任务,没有 has_more 续跑语义;下一次 5 分钟调度会重新生成完整榜单。
return &userv1.CronBatchResponse{
ClaimedCount: int32(processed),
ProcessedCount: int32(processed),
SuccessCount: int32(processed),
HasMore: false,
}, nil
}
func durationFromMillis(value int64) time.Duration {
if value <= 0 {
return 0
}
return time.Duration(value) * time.Millisecond
}
func normalizedBatchSize(value int32, fallback int) int {
if value <= 0 {
return fallback
}
return int(value)
}