feat: Enhance dependency injection and service integration
- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
This commit is contained in:
@@ -3,22 +3,28 @@ package service
|
||||
import (
|
||||
"carrotskin/internal/model"
|
||||
"carrotskin/internal/repository"
|
||||
"carrotskin/pkg/database"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// profileServiceImpl ProfileService的实现
|
||||
type profileServiceImpl struct {
|
||||
// profileService ProfileService的实现
|
||||
type profileService struct {
|
||||
profileRepo repository.ProfileRepository
|
||||
userRepo repository.UserRepository
|
||||
cache *database.CacheManager
|
||||
cacheKeys *database.CacheKeyBuilder
|
||||
cacheInv *database.CacheInvalidator
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
@@ -26,16 +32,20 @@ type profileServiceImpl struct {
|
||||
func NewProfileService(
|
||||
profileRepo repository.ProfileRepository,
|
||||
userRepo repository.UserRepository,
|
||||
cacheManager *database.CacheManager,
|
||||
logger *zap.Logger,
|
||||
) ProfileService {
|
||||
return &profileServiceImpl{
|
||||
return &profileService{
|
||||
profileRepo: profileRepo,
|
||||
userRepo: userRepo,
|
||||
cache: cacheManager,
|
||||
cacheKeys: database.NewCacheKeyBuilder(""),
|
||||
cacheInv: database.NewCacheInvalidator(cacheManager),
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) Create(userID int64, name string) (*model.Profile, error) {
|
||||
func (s *profileService) Create(ctx context.Context, userID int64, name string) (*model.Profile, error) {
|
||||
// 验证用户存在
|
||||
user, err := s.userRepo.FindByID(userID)
|
||||
if err != nil || user == nil {
|
||||
@@ -79,29 +89,64 @@ func (s *profileServiceImpl) Create(userID int64, name string) (*model.Profile,
|
||||
return nil, fmt.Errorf("设置活跃状态失败: %w", err)
|
||||
}
|
||||
|
||||
// 清除用户的 profile 列表缓存
|
||||
s.cacheInv.OnCreate(ctx, s.cacheKeys.ProfileList(userID))
|
||||
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) GetByUUID(uuid string) (*model.Profile, error) {
|
||||
profile, err := s.profileRepo.FindByUUID(uuid)
|
||||
func (s *profileService) GetByUUID(ctx context.Context, uuid string) (*model.Profile, error) {
|
||||
// 尝试从缓存获取
|
||||
cacheKey := s.cacheKeys.Profile(uuid)
|
||||
var profile model.Profile
|
||||
if err := s.cache.Get(ctx, cacheKey, &profile); err == nil {
|
||||
return &profile, nil
|
||||
}
|
||||
|
||||
// 缓存未命中,从数据库查询
|
||||
profile2, err := s.profileRepo.FindByUUID(uuid)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrProfileNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("查询档案失败: %w", err)
|
||||
}
|
||||
return profile, nil
|
||||
|
||||
// 存入缓存(异步,5分钟过期)
|
||||
if profile2 != nil {
|
||||
go func() {
|
||||
_ = s.cache.Set(context.Background(), cacheKey, profile2, 5*time.Minute)
|
||||
}()
|
||||
}
|
||||
|
||||
return profile2, nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) GetByUserID(userID int64) ([]*model.Profile, error) {
|
||||
func (s *profileService) GetByUserID(ctx context.Context, userID int64) ([]*model.Profile, error) {
|
||||
// 尝试从缓存获取
|
||||
cacheKey := s.cacheKeys.ProfileList(userID)
|
||||
var profiles []*model.Profile
|
||||
if err := s.cache.Get(ctx, cacheKey, &profiles); err == nil {
|
||||
return profiles, nil
|
||||
}
|
||||
|
||||
// 缓存未命中,从数据库查询
|
||||
profiles, err := s.profileRepo.FindByUserID(userID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询档案列表失败: %w", err)
|
||||
}
|
||||
|
||||
// 存入缓存(异步,3分钟过期)
|
||||
if profiles != nil {
|
||||
go func() {
|
||||
_ = s.cache.Set(context.Background(), cacheKey, profiles, 3*time.Minute)
|
||||
}()
|
||||
}
|
||||
|
||||
return profiles, nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) Update(uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error) {
|
||||
func (s *profileService) Update(ctx context.Context, uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error) {
|
||||
// 获取档案并验证权限
|
||||
profile, err := s.profileRepo.FindByUUID(uuid)
|
||||
if err != nil {
|
||||
@@ -139,10 +184,16 @@ func (s *profileServiceImpl) Update(uuid string, userID int64, name *string, ski
|
||||
return nil, fmt.Errorf("更新档案失败: %w", err)
|
||||
}
|
||||
|
||||
// 清除该 profile 和用户列表的缓存
|
||||
s.cacheInv.OnUpdate(ctx,
|
||||
s.cacheKeys.Profile(uuid),
|
||||
s.cacheKeys.ProfileList(userID),
|
||||
)
|
||||
|
||||
return s.profileRepo.FindByUUID(uuid)
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) Delete(uuid string, userID int64) error {
|
||||
func (s *profileService) Delete(ctx context.Context, uuid string, userID int64) error {
|
||||
// 获取档案并验证权限
|
||||
profile, err := s.profileRepo.FindByUUID(uuid)
|
||||
if err != nil {
|
||||
@@ -159,10 +210,17 @@ func (s *profileServiceImpl) Delete(uuid string, userID int64) error {
|
||||
if err := s.profileRepo.Delete(uuid); err != nil {
|
||||
return fmt.Errorf("删除档案失败: %w", err)
|
||||
}
|
||||
|
||||
// 清除该 profile 和用户列表的缓存
|
||||
s.cacheInv.OnDelete(ctx,
|
||||
s.cacheKeys.Profile(uuid),
|
||||
s.cacheKeys.ProfileList(userID),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) SetActive(uuid string, userID int64) error {
|
||||
func (s *profileService) SetActive(ctx context.Context, uuid string, userID int64) error {
|
||||
// 获取档案并验证权限
|
||||
profile, err := s.profileRepo.FindByUUID(uuid)
|
||||
if err != nil {
|
||||
@@ -184,10 +242,13 @@ func (s *profileServiceImpl) SetActive(uuid string, userID int64) error {
|
||||
return fmt.Errorf("更新使用时间失败: %w", err)
|
||||
}
|
||||
|
||||
// 清除该用户所有 profile 的缓存(因为活跃状态改变了)
|
||||
s.cacheInv.BatchInvalidate(ctx, s.cacheKeys.ProfilePattern(userID))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) CheckLimit(userID int64, maxProfiles int) error {
|
||||
func (s *profileService) CheckLimit(ctx context.Context, userID int64, maxProfiles int) error {
|
||||
count, err := s.profileRepo.CountByUserID(userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询档案数量失败: %w", err)
|
||||
@@ -199,7 +260,7 @@ func (s *profileServiceImpl) CheckLimit(userID int64, maxProfiles int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) GetByNames(names []string) ([]*model.Profile, error) {
|
||||
func (s *profileService) GetByNames(ctx context.Context, names []string) ([]*model.Profile, error) {
|
||||
profiles, err := s.profileRepo.GetByNames(names)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查找失败: %w", err)
|
||||
@@ -207,7 +268,8 @@ func (s *profileServiceImpl) GetByNames(names []string) ([]*model.Profile, error
|
||||
return profiles, nil
|
||||
}
|
||||
|
||||
func (s *profileServiceImpl) GetByProfileName(name string) (*model.Profile, error) {
|
||||
func (s *profileService) GetByProfileName(ctx context.Context, name string) (*model.Profile, error) {
|
||||
// Profile name 查询通常不会频繁缓存,但为了一致性也添加
|
||||
profile, err := s.profileRepo.FindByName(name)
|
||||
if err != nil {
|
||||
return nil, errors.New("用户角色未创建")
|
||||
@@ -230,5 +292,3 @@ func generateRSAPrivateKeyInternal() (string, error) {
|
||||
|
||||
return string(privateKeyPEM), nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user