190 lines
7.9 KiB
Go
190 lines
7.9 KiB
Go
package grpc
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
|
||
activityv1 "hyapp.local/api/proto/activity/v1"
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/xerr"
|
||
achievementservice "hyapp/services/activity-service/internal/service/achievement"
|
||
agencyopeningservice "hyapp/services/activity-service/internal/service/agencyopening"
|
||
cpweeklyrankservice "hyapp/services/activity-service/internal/service/cpweeklyrank"
|
||
growthservice "hyapp/services/activity-service/internal/service/growth"
|
||
messageservice "hyapp/services/activity-service/internal/service/message"
|
||
roomturnoverrewardservice "hyapp/services/activity-service/internal/service/roomturnoverreward"
|
||
weeklystarservice "hyapp/services/activity-service/internal/service/weeklystar"
|
||
)
|
||
|
||
// CronServer exposes activity-service owned background batches to cron-service.
|
||
type CronServer struct {
|
||
activityv1.UnimplementedActivityCronServiceServer
|
||
|
||
message *messageservice.Service
|
||
growth *growthservice.Service
|
||
achievement *achievementservice.Service
|
||
weeklyStar *weeklystarservice.Service
|
||
roomReward *roomturnoverrewardservice.Service
|
||
agencyOpen *agencyopeningservice.Service
|
||
cpWeekly *cpweeklyrankservice.Service
|
||
}
|
||
|
||
// NewCronServer creates the internal cron adapter without exposing message storage.
|
||
func NewCronServer(messageSvc *messageservice.Service, growthSvc *growthservice.Service, achievementSvc *achievementservice.Service, weeklyStarSvc *weeklystarservice.Service, roomRewardSvc *roomturnoverrewardservice.Service, agencyOpeningSvc *agencyopeningservice.Service, cpWeeklyRankSvc *cpweeklyrankservice.Service) *CronServer {
|
||
server := &CronServer{message: messageSvc}
|
||
server.growth = growthSvc
|
||
server.achievement = achievementSvc
|
||
server.weeklyStar = weeklyStarSvc
|
||
server.roomReward = roomRewardSvc
|
||
server.agencyOpen = agencyOpeningSvc
|
||
server.cpWeekly = cpWeeklyRankSvc
|
||
return server
|
||
}
|
||
|
||
// ProcessMessageFanoutBatch claims and processes one message fanout page.
|
||
func (s *CronServer) ProcessMessageFanoutBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.message == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "message service is not configured"))
|
||
}
|
||
processed, err := s.message.ProcessNextFanoutJob(ctx, messageservice.FanoutWorkerOptions{
|
||
WorkerID: req.GetWorkerId(),
|
||
BatchSize: int(req.GetBatchSize()),
|
||
LockTTL: durationFromMillis(req.GetLockTtlMs()),
|
||
})
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
if !processed {
|
||
return &activityv1.CronBatchResponse{}, nil
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: 1,
|
||
ProcessedCount: 1,
|
||
SuccessCount: 1,
|
||
HasMore: true,
|
||
}, nil
|
||
}
|
||
|
||
// ProcessLevelRewardBatch claims and grants pending permanent level rewards.
|
||
func (s *CronServer) ProcessLevelRewardBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.growth == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "growth service is not configured"))
|
||
}
|
||
claimed, processed, success, failure, hasMore, err := s.growth.ProcessLevelRewardBatch(ctx, req.GetRunId(), req.GetWorkerId(), int(req.GetBatchSize()), durationFromMillis(req.GetLockTtlMs()))
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: claimed,
|
||
ProcessedCount: processed,
|
||
SuccessCount: success,
|
||
FailureCount: failure,
|
||
HasMore: hasMore,
|
||
}, nil
|
||
}
|
||
|
||
// ProcessAchievementRewardBatch claims and grants pending achievement badge/resource rewards.
|
||
func (s *CronServer) ProcessAchievementRewardBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.achievement == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "achievement service is not configured"))
|
||
}
|
||
claimed, processed, success, failure, hasMore, err := s.achievement.ProcessAchievementRewardBatch(ctx, req.GetRunId(), req.GetWorkerId(), int(req.GetBatchSize()), durationFromMillis(req.GetLockTtlMs()))
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: claimed,
|
||
ProcessedCount: processed,
|
||
SuccessCount: success,
|
||
FailureCount: failure,
|
||
HasMore: hasMore,
|
||
}, nil
|
||
}
|
||
|
||
// ProcessWeeklyStarSettlementBatch claims ended weekly-star cycles and grants Top rewards.
|
||
func (s *CronServer) ProcessWeeklyStarSettlementBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.weeklyStar == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "weekly star service is not configured"))
|
||
}
|
||
claimed, processed, success, failure, hasMore, err := s.weeklyStar.ProcessSettlementBatch(ctx, req.GetRunId(), req.GetWorkerId(), req.GetBatchSize(), durationFromMillis(req.GetLockTtlMs()))
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: claimed,
|
||
ProcessedCount: processed,
|
||
SuccessCount: success,
|
||
FailureCount: failure,
|
||
HasMore: hasMore,
|
||
}, nil
|
||
}
|
||
|
||
// ProcessCPWeeklyRankSettlementBatch closes the previous UTC CP week and grants configured Top rewards.
|
||
func (s *CronServer) ProcessCPWeeklyRankSettlementBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.cpWeekly == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "cp weekly rank service is not configured"))
|
||
}
|
||
claimed, processed, success, failure, hasMore, err := s.cpWeekly.ProcessSettlementBatch(ctx, req.GetRunId(), req.GetWorkerId(), req.GetBatchSize())
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: claimed,
|
||
ProcessedCount: processed,
|
||
SuccessCount: success,
|
||
FailureCount: failure,
|
||
HasMore: hasMore,
|
||
}, nil
|
||
}
|
||
|
||
// ProcessRoomTurnoverRewardSettlementBatch closes the previous UTC week and grants pending room rewards.
|
||
func (s *CronServer) ProcessRoomTurnoverRewardSettlementBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
// cron-service 只负责调度,activity-service 才拥有上一 UTC 周期认领 settlement 和发奖状态机。
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.roomReward == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "room turnover reward service is not configured"))
|
||
}
|
||
result, err := s.roomReward.ProcessSettlementBatch(ctx, int(req.GetBatchSize()))
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: result.ClaimedCount,
|
||
ProcessedCount: result.ProcessedCount,
|
||
SuccessCount: result.SuccessCount,
|
||
FailureCount: result.FailureCount,
|
||
HasMore: result.HasMore,
|
||
}, nil
|
||
}
|
||
|
||
// ProcessAgencyOpeningSettlementBatch claims ended agency-opening cycles and grants leaderboard COIN rewards.
|
||
func (s *CronServer) ProcessAgencyOpeningSettlementBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) {
|
||
ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
|
||
if s.agencyOpen == nil {
|
||
return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "agency opening service is not configured"))
|
||
}
|
||
claimed, processed, success, failure, hasMore, err := s.agencyOpen.ProcessSettlementBatch(ctx, req.GetRunId(), req.GetWorkerId(), req.GetBatchSize(), durationFromMillis(req.GetLockTtlMs()))
|
||
if err != nil {
|
||
return nil, xerr.ToGRPCError(err)
|
||
}
|
||
return &activityv1.CronBatchResponse{
|
||
ClaimedCount: claimed,
|
||
ProcessedCount: processed,
|
||
SuccessCount: success,
|
||
FailureCount: failure,
|
||
HasMore: hasMore,
|
||
}, nil
|
||
}
|
||
|
||
func durationFromMillis(value int64) time.Duration {
|
||
if value <= 0 {
|
||
return 0
|
||
}
|
||
return time.Duration(value) * time.Millisecond
|
||
}
|