103 lines
3.7 KiB
Go
103 lines
3.7 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"
|
|
growthservice "hyapp/services/activity-service/internal/service/growth"
|
|
messageservice "hyapp/services/activity-service/internal/service/message"
|
|
)
|
|
|
|
// CronServer exposes activity-service owned background batches to cron-service.
|
|
type CronServer struct {
|
|
activityv1.UnimplementedActivityCronServiceServer
|
|
|
|
message *messageservice.Service
|
|
growth *growthservice.Service
|
|
achievement *achievementservice.Service
|
|
}
|
|
|
|
// NewCronServer creates the internal cron adapter without exposing message storage.
|
|
func NewCronServer(messageSvc *messageservice.Service, growthSvc *growthservice.Service, achievementSvc ...*achievementservice.Service) *CronServer {
|
|
server := &CronServer{message: messageSvc}
|
|
server.growth = growthSvc
|
|
if len(achievementSvc) > 0 {
|
|
server.achievement = achievementSvc[0]
|
|
}
|
|
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
|
|
}
|
|
|
|
func durationFromMillis(value int64) time.Duration {
|
|
if value <= 0 {
|
|
return 0
|
|
}
|
|
return time.Duration(value) * time.Millisecond
|
|
}
|