refactor(server): decouple services and improve architecture
All checks were successful
Build Backend / build (push) Successful in 4m55s
Build Backend / build-docker (push) Successful in 10m34s

- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
This commit is contained in:
2026-06-15 03:41:59 +08:00
parent 9951043034
commit d9aa4b46c3
78 changed files with 2156 additions and 1640 deletions

View File

@@ -5,6 +5,7 @@ import (
"errors"
"with_you/internal/dto"
apperrors "with_you/internal/errors"
"with_you/internal/model"
"with_you/internal/repository"
)
@@ -291,48 +292,36 @@ func (s *adminGroupServiceImpl) RemoveMember(ctx context.Context, groupID string
}
// TransferOwner 转让群主
// 委托 groupRepo.TransferOwner 在单个数据库事务内原子完成:
// - 更新 group.owner_id 为新群主
// - 原群主角色降级为普通成员
// - 新群主角色升级为 owner
//
// 任何一步失败都会整体回滚,避免出现「两个群主」或「零群主」的数据不一致。
func (s *adminGroupServiceImpl) TransferOwner(ctx context.Context, groupID string, newOwnerID string) (*dto.AdminGroupDetailResponse, error) {
// 先检查群组是否存在
// 校验群组存在
group, err := s.groupRepo.GetByID(groupID)
if err != nil {
return nil, errors.New("群组不存在")
return nil, apperrors.ErrGroupNotFound
}
// 检查新群主是否是群成员
// 校验新群主是群成员
newOwnerMember, err := s.groupRepo.GetMember(groupID, newOwnerID)
if err != nil {
return nil, errors.New("新群主不是群组成员")
return nil, apperrors.ErrNotGroupMember
}
// 新群主已是群主则无需转让
if newOwnerMember.Role == model.GroupRoleOwner {
return nil, apperrors.ErrInvalidOperation
}
// 获取当前群主信息
currentOwnerMember, err := s.groupRepo.GetMember(groupID, group.OwnerID)
if err != nil {
return nil, errors.New("当前群主信息不存在")
// 校验当前群主信息存在
if _, err := s.groupRepo.GetMember(groupID, group.OwnerID); err != nil {
return nil, apperrors.ErrGroupNotFound
}
oldOwnerID := group.OwnerID
// 更新当前群主为普通成员
err = s.groupRepo.SetMemberRole(groupID, oldOwnerID, model.GroupRoleMember)
if err != nil {
return nil, err
}
// 更新新群主角色
err = s.groupRepo.SetMemberRole(groupID, newOwnerID, model.GroupRoleOwner)
if err != nil {
// 回滚
_ = s.groupRepo.SetMemberRole(groupID, oldOwnerID, model.GroupRoleOwner)
return nil, err
}
// 更新群组的OwnerID
group.OwnerID = newOwnerID
err = s.groupRepo.Update(group)
if err != nil {
// 回滚
_ = s.groupRepo.SetMemberRole(groupID, oldOwnerID, model.GroupRoleOwner)
_ = s.groupRepo.SetMemberRole(groupID, newOwnerID, newOwnerMember.Role)
// 原子转让:所有写入在 groupRepo.TransferOwner 的单个事务内完成
if err := s.groupRepo.TransferOwner(groupID, group.OwnerID, newOwnerID); err != nil {
return nil, err
}
@@ -373,7 +362,5 @@ func (s *adminGroupServiceImpl) TransferOwner(ctx context.Context, groupID strin
}
}
_ = currentOwnerMember // 避免 unused variable 警告
return response, nil
}