package service import ( "errors" "fmt" "sync" "time" "git.urec56.ru/urec/chat_back_go/internal/domain" "git.urec56.ru/urec/chat_back_go/internal/logger" "git.urec56.ru/urec/chat_back_go/internal/repository" ) type userService struct { cache Cache m *sync.Map ur repository.User auth Auth l *logger.Logger } type userCache struct { u domain.User expiresAt time.Time } func newUserService(user repository.User, auth Auth, l *logger.Logger, cache Cache) *userService { return &userService{ur: user, auth: auth, l: l, cache: cache, m: &sync.Map{}} } func (s *userService) GetCachedUser(userID int) (domain.User, error) { item, ok := s.m.Load(userID) if ok { if userData, ok := item.(userCache); ok && userData.expiresAt.After(time.Now()) { return userData.u, nil } } u, err := s.Get(userID) if err != nil { s.l.Infof("error getting user by id: %s", err.Error()) return domain.User{}, domain.UserNotFoundError } s.SetCachedUser(u) return u, nil } func (s *userService) SetCachedUser(u domain.User) { s.m.Store(u.ID, userCache{u: u, expiresAt: time.Now().Add(time.Minute)}) } func (s *userService) Get(userID int) (domain.User, error) { u := domain.User{} err := s.cache.Get(fmt.Sprintf("user: {'id': %d}", userID), &u) if err == nil { return u, nil } s.l.Infof("error getting user from cache: %s", err.Error()) u, err = s.ur.GetByID(userID) if err != nil { return u, err } if err = s.cache.Set(fmt.Sprintf("user: {'id': %d}", userID), u, time.Second*20); err != nil { s.l.Infof("error setting user to cache: %s", err.Error()) } return u, nil } func (s *userService) GetVerificated(userID int) (domain.User, error) { u, err := s.ur.GetByID(userID) if err != nil { return u, err } if u.Role < domain.VerificatedUser { return u, domain.UnverifiedUserError } return u, err } func (s *userService) GetAll(username string) ([]domain.User, error) { users, err := s.ur.GetAll(username) return users, err } func (s *userService) FindOne(username, email string) (domain.User, error) { user, err := s.ur.FindOne(username, email) if err != nil { return domain.User{}, domain.InternalServerError } return user, nil } func (s *userService) Register(userData domain.UserRegister) (string, error) { hashedPassword, err := s.auth.HashPassword(userData.Password) if err != nil { return "", domain.InternalServerError } user, err := s.ur.Register(userData.Email, hashedPassword, userData.Username, userData.DateOfBirth.Time) if err != nil { if errors.Is(err, domain.UserAlreadyExistsError) { return "", err } return "", domain.InternalServerError } authToken, err := s.auth.EncodeAuthToken(user.ID) if err != nil { return "", domain.InternalServerError } return authToken, err }