fix(n+1): 批量查询替代循环单查

- IsAdminBootstrapRequired: userRepo.GetByID 循环 → GetByIDs 批量
- AssignRoles: roleRepo.GetByID 循环 → GetByIDs 批量
- 在 userRepositoryInterface 补充 GetByIDs 方法签名
This commit is contained in:
2026-05-08 08:05:26 +08:00
parent 9b1cea246e
commit 2a18a6fb47
39 changed files with 3169 additions and 393 deletions

View File

@@ -30,27 +30,15 @@ func (s *AuthService) RegisterOAuthProvider(provider auth.OAuthProvider, cfg *au
}
func (s *AuthService) findUserForLogin(ctx context.Context, account string) (*domain.User, error) {
user, err := s.userRepo.GetByUsername(ctx, account)
if err == nil {
return user, nil
// P1性能优化使用单一查询替代 username->email->phone 串行查询减少DB往返
user, err := s.userRepo.FindByAccount(ctx, account)
if err != nil {
if isUserNotFoundError(err) {
return nil, err
}
return nil, fmt.Errorf("lookup user failed: %w", err)
}
if !isUserNotFoundError(err) {
return nil, fmt.Errorf("lookup user by username failed: %w", err)
}
user, err = s.userRepo.GetByEmail(ctx, account)
if err == nil {
return user, nil
}
if !isUserNotFoundError(err) {
return nil, fmt.Errorf("lookup user by email failed: %w", err)
}
user, err = s.userRepo.GetByPhone(ctx, account)
if err != nil && !isUserNotFoundError(err) {
return nil, fmt.Errorf("lookup user by phone failed: %w", err)
}
return user, err
return user, nil
}
func isUserNotFoundError(err error) bool {
@@ -100,9 +88,19 @@ func (s *AuthService) bestEffortUpdateLastLogin(ctx context.Context, userID int6
return
}
if err := s.userRepo.UpdateLastLogin(ctx, userID, ip); err != nil {
log.Printf("auth: update last login failed, source=%s user_id=%d ip=%s err=%v", source, userID, ip, err)
}
// PERF-01: 改为异步 goroutine不阻塞登录响应返回
go func() {
defer func() {
if r := recover(); r != nil {
log.Printf("auth: update last login panic recovered, source=%s user_id=%d err=%v", source, userID, r)
}
}()
bgCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := s.userRepo.UpdateLastLogin(bgCtx, userID, ip); err != nil {
log.Printf("auth: update last login failed, source=%s user_id=%d ip=%s err=%v", source, userID, ip, err)
}
}()
}
func loginAttemptKey(account string, user *domain.User) string {